am 9f41befb: am 9afafd0e: Merge "Restrict phantom sudden move event hack to specific device" into jb-dev

* commit '9f41befb8b5f4d86a03f9eb7e2d80148e9b55428':
  Restrict phantom sudden move event hack to specific device
diff --git a/java/proguard.flags b/java/proguard.flags
index 34e23aa..752ced3 100644
--- a/java/proguard.flags
+++ b/java/proguard.flags
@@ -41,13 +41,7 @@
 }
 
 -keep class com.android.inputmethod.latin.ResearchLogger {
-  void setLogFileManager(...);
-  void clearAll();
-  com.android.inputmethod.latin.ResearchLogger$LogFileManager getLogFileManager();
-}
-
--keep class com.android.inputmethod.latin.ResearchLogger$LogFileManager {
-  java.lang.String getContents();
+  void flush();
 }
 
 -keep class com.android.inputmethod.keyboard.KeyboardLayoutSet$Builder {
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 086d2d8..87821d4 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Stoor"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Taal"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Uitleg"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Jou gepasmaakte invoerstyl moet geaktiveer word voor gebruik. Wil jy nou aktiveer?"</string>
-    <string name="enable" msgid="5031294444630523247">"Aktiveer"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Bruikbaarheidstudie-modus"</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>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 012d014..ec2a892 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"አስቀምጥ"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"ቋንቋ"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"አቀማመጥ"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"የተበጀው የግብዓት ቅጥህን ከመጠቀምህ በፊት መንቃት አለበት። አሁን ማንቃት ትፈልጋለህ?"</string>
-    <string name="enable" msgid="5031294444630523247">"አንቃ"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"የተገልጋይነት ጥናት ሁነታ"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"ቁልፍ ተጫን በቅንጅቶች ወቅት ንዝረት"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"ቁልፍ ተጫን የድምጽ መጠን ቅንብሮች"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 5bd9d8c..3c51ba1 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"حفظ"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"اللغة"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"التخطيط"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"يجب تمكين نمط الإدخال المخصص قبل استخدامه. هل تريد تمكينه الآن؟"</string>
-    <string name="enable" msgid="5031294444630523247">"تمكين"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"وضع سهولة الاستخدام"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"إعدادات مدة اهتزاز الضغط على المفاتيح"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"إعدادات مستوى صوت الضغط على المفاتيح"</string>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index d5e26a8..b4a73a4 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Захаваць"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Мова"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Раскладка"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Карыстальніцкі метад уводу павінен быць уключаны, перш чым пачаць выкарыстоўваць яго. Жадаеце ўключыць яго зараз?"</string>
-    <string name="enable" msgid="5031294444630523247">"Уключыць"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Рэжым даследвання выкарыстальнасці"</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>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 026f5aa..d1c0f9f 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Запазване"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Език"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Подредба"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Персонализираният ви стил за въвеждане трябва да се активира, преди да започнете да го използвате. Искате ли да го направите сега?"</string>
-    <string name="enable" msgid="5031294444630523247">"Активиране"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим за изучаване на използваемостта"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки за продължителност на вибрирането при натискане на клавиш"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки за силата на звука при натискане на клавиш"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 6a9adb1..49dca9c 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Desa"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Disseny"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"El teu estil d\'entrada personalitzat ha d\'estar activat per poder fer-lo servir. Vols activar-lo ara?"</string>
-    <string name="enable" msgid="5031294444630523247">"Activa"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'estudi d\'usabilitat"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Configuració de la durada de les vibracions per pulsació de tecla"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Configuració del volum de so de pulsació de tecla"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 7ffd368..681667c 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -31,16 +31,16 @@
     <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>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk při stisku klávesy"</string>
-    <string name="popup_on_keypress" msgid="123894815723512944">"Detail znaku při stisku klávesy"</string>
+    <string name="popup_on_keypress" msgid="123894815723512944">"Zobrazit znaky při stisku klávesy"</string>
     <string name="general_category" msgid="1859088467017573195">"Obecné"</string>
     <string name="correction_category" msgid="2236750915056607613">"Oprava textu"</string>
     <string name="misc_category" msgid="6894192814868233453">"Další možnosti"</string>
     <string name="advanced_settings" msgid="362895144495591463">"Pokročilá nastavení"</string>
     <string name="advanced_settings_summary" msgid="4487980456152830271">"Možnosti pro odborníky"</string>
-    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Přepnout na jiné metody zad."</string>
+    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Přep. na jiné metody zad."</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Klávesa pro přepínání jazyka ovládá i další metody zadávání"</string>
-    <string name="suppress_language_switch_key" msgid="8003788410354806368">"Zakázat kláv. přepínání jazyka"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Prodleva vysk. okna klávesnice"</string>
+    <string name="suppress_language_switch_key" msgid="8003788410354806368">"Zakázat kl. přep. jazyka"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Prodleva vysk. okna kláv."</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez prodlevy"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Výchozí"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Navrhovat jména kontaktů"</string>
@@ -61,9 +61,9 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mírné"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivní"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Velmi agresivní"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Návrh dalšího slova"</string>
+    <string name="bigram_suggestion" msgid="8169311444438922902">"Návrhy dalšího slova"</string>
     <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Použít předchozí slovo ke zlepšení návrhů"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Odhad dalšího slova"</string>
+    <string name="bigram_prediction" msgid="3216364899483135294">"Návrh dalšího slova"</string>
     <string name="bigram_prediction_summary" msgid="1747261921174300098">"Použít předchozí slovo také pro odhad"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Uloženo"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Přejít"</string>
@@ -101,18 +101,18 @@
     <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Režim písmen"</string>
     <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Režim telefonu"</string>
     <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Režim telefonních symbolů"</string>
-    <string name="voice_input" msgid="3583258583521397548">"Klávesa hlasového vstupu"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Klíč hlasového vstupu"</string>
     <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na hlavní klávesnici"</string>
-    <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici se symboly"</string>
+    <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici se symb."</string>
     <string name="voice_input_modes_off" msgid="3745699748218082014">"Vypnuto"</string>
-    <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na hlavní klávesnici"</string>
-    <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon na klávesnici se symboly"</string>
+    <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. na hlav. kláv."</string>
+    <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. na kláv. se symb."</string>
     <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="configure_input_method" msgid="373356270290742459">"Konfigurace metod vstupu"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Vstupní jazyky"</string>
-    <string name="select_language" msgid="3693815588777926848">"Vstupní jazyky"</string>
+    <string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</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="has_dictionary" msgid="6071847973466625007">"K dispozici je slovník"</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>
     <string name="keyboard_layout" msgid="8451164783510487501">"Motiv klávesnice"</string>
@@ -127,18 +127,20 @@
     <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Žádný jazyk (Dvorak)"</string>
     <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Žádný jazyk (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Žádný jazyk (PC)"</string>
-    <string name="custom_input_styles_title" msgid="8429952441821251512">"Vlastní styl zadávání"</string>
+    <string name="custom_input_styles_title" msgid="8429952441821251512">"Vlastní styly vstupu"</string>
     <string name="add_style" msgid="6163126614514489951">"Přidat styl"</string>
     <string name="add" msgid="8299699805688017798">"Přidat"</string>
     <string name="remove" msgid="4486081658752944606">"Odebrat"</string>
     <string name="save" msgid="7646738597196767214">"Uložit"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Jazyk"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Rozvržení"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Vlastní styl vstupu musíte nejdříve povolit. Povolit?"</string>
-    <string name="enable" msgid="5031294444630523247">"Povolit"</string>
-    <string name="not_now" msgid="6172462888202790482">"Teď ne"</string>
-    <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Stejný styl vstupu již existuje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim studie použitelnosti"</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>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Nastavení trvání vibrace při stisku klávesy"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Nastavení hlasitosti zvuku při stisknutí klávesy"</string>
 </resources>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 3460f5f..801f9fe 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Gem"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Sprog"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Din tilpassede indtastningsmetode skal være aktiveret, før du begynder at bruge den. Vil du gøre det nu?"</string>
-    <string name="enable" msgid="5031294444630523247">"Aktivér"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tilstand for brugsstudie"</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>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index ffd27c3..820e356 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Speichern"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Sprache"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Ihr benutzerdefinierter Eingabestil muss vor der Verwendung aktiviert werden. Möchten Sie ihn jetzt aktivieren?"</string>
-    <string name="enable" msgid="5031294444630523247">"Aktivieren"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus der Studie zur Benutzerfreundlichkeit"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Einstellungen für Vibrationsdauer bei Tastendruck"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Einstellungen für Tonlautstärke bei Tastendruck"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 95d2441..2a5b269 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Αποθήκευση"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Γλώσσα"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Διάταξη"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Απαιτείται ενεργοποίηση προσαρμ. στυλ εισόδου. Να γίνει τώρα;"</string>
-    <string name="enable" msgid="5031294444630523247">"Ενεργοποίηση"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Λειτουργία μελέτης χρηστικότητας"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Ρυθμίσεις διάρκειας δόνησης κατά το πάτημα πλήκτρων"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Ρυθμίσεις έντασης ήχου κατά το πάτημα πλήκτρων"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 023f97d..7e93e48 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -38,7 +38,7 @@
     <string name="advanced_settings" msgid="362895144495591463">"Advanced settings"</string>
     <string name="advanced_settings_summary" msgid="4487980456152830271">"Options for experts"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Switch to other input methods"</string>
-    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Language switch key also covers other input methods"</string>
+    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Language switch key covers other input methods too"</string>
     <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suppress language switch key"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Key pop-up dismiss delay"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"No delay"</string>
@@ -53,10 +53,10 @@
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Show correction suggestions"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Display suggested words while typing"</string>
     <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Always show"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Show in portrait mode"</string>
+    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Show on portrait mode"</string>
     <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Always hide"</string>
     <string name="auto_correction" msgid="4979925752001319458">"Auto-correction"</string>
-    <string name="auto_correction_summary" msgid="5625751551134658006">"Correct mistyped words automatically with spacebar and punctuation"</string>
+    <string name="auto_correction_summary" msgid="5625751551134658006">"Spacebar and punctuation correct mistyped words automatically"</string>
     <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Off"</string>
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressive"</string>
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Save"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Language"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Your custom input style needs to be enabled before you start using it. Do you want to enable it now?"</string>
-    <string name="enable" msgid="5031294444630523247">"Enable"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Usability study mode"</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>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index bae0a6d..a98f5c5 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -37,9 +37,9 @@
     <string name="misc_category" msgid="6894192814868233453">"Otras opciones"</string>
     <string name="advanced_settings" msgid="362895144495591463">"Configuración avanzada"</string>
     <string name="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string>
-    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de entrada"</string>
-    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma abarca otros métodos de entrada."</string>
-    <string name="suppress_language_switch_key" msgid="8003788410354806368">"Elim. tecla cambio de idioma"</string>
+    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de introd."</string>
+    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma abarca otros métodos de introd."</string>
+    <string name="suppress_language_switch_key" msgid="8003788410354806368">"Supr. tecla cambio idioma"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso en rechazo de alerta de tecla"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin demora"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminada"</string>
@@ -127,18 +127,20 @@
     <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Sin idioma (Dvorak)"</string>
     <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Sin idioma (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Sin idioma (PC)"</string>
-    <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos de entrada personalizados"</string>
+    <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos entrada pers."</string>
     <string name="add_style" msgid="6163126614514489951">"Agr. estilo"</string>
     <string name="add" msgid="8299699805688017798">"Agregar"</string>
     <string name="remove" msgid="4486081658752944606">"Eliminar"</string>
     <string name="save" msgid="7646738597196767214">"Guardar"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Diseño"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Debes activar estilo de entrada personalizado para utilizarlo."</string>
-    <string name="enable" msgid="5031294444630523247">"Activar"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudio de usabilidad"</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>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Configuración de la duración de vibraciones al presionar las teclas"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Configuración del volumen de sonio al presionar las teclas"</string>
 </resources>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 18b413a..01ef3bb 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -24,33 +24,33 @@
     <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
     <string name="english_ime_settings" msgid="6661589557206947774">"Ajustes del teclado de Android"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones introducción texto"</string>
-    <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector de Android"</string>
-    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector de Android (AOSP)"</string>
+    <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortográfico de Android"</string>
+    <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortográfico de Android (AOSP)"</string>
     <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ajustes del corrector ortográfico"</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="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres de 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 tecla"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Sonido al pulsar tecla"</string>
-    <string name="popup_on_keypress" msgid="123894815723512944">"Ampliar al pulsar tecla"</string>
+    <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up al pulsar tecla"</string>
     <string name="general_category" msgid="1859088467017573195">"General"</string>
     <string name="correction_category" msgid="2236750915056607613">"Corrección ortográfica"</string>
     <string name="misc_category" msgid="6894192814868233453">"Otras opciones"</string>
     <string name="advanced_settings" msgid="362895144495591463">"Ajustes avanzados"</string>
     <string name="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de introducción"</string>
-    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma sirve también para otros métodos"</string>
-    <string name="suppress_language_switch_key" msgid="8003788410354806368">"Quitar tecla de idioma"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso al ampliar tecla"</string>
+    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma sirve también para otros métodos."</string>
+    <string name="suppress_language_switch_key" msgid="8003788410354806368">"Eliminar tecla cambiar idioma"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso de rechazo"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin retraso"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
-    <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir contactos"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nombres contactos"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nombres de contactos para sugerencias y correcciones"</string>
     <string name="enable_span_insert" msgid="7204653105667167620">"Activar nuevas correcciones"</string>
     <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para nuevas correcciones"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
-    <string name="prefs_show_suggestions" msgid="8026799663445531637">"Sugerencias de correcciones"</string>
+    <string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar sugerencias de correcciones"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Muestra las palabras sugeridas mientras se escribe."</string>
     <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar siempre"</string>
     <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar en modo vertical"</string>
@@ -61,9 +61,9 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Parcial"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresiva"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerir siguiente palabra"</string>
+    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerencias de la siguiente palabra"</string>
     <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palabra anterior para mejorar las sugerencias"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Predecir siguiente palabra"</string>
+    <string name="bigram_prediction" msgid="3216364899483135294">"Predicción de la siguiente palabra"</string>
     <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilizar también la palabra anterior para realizar la predicción"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
@@ -106,7 +106,7 @@
     <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"En teclado de símbolos"</string>
     <string name="voice_input_modes_off" msgid="3745699748218082014">"Desactivada"</string>
     <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en teclado principal"</string>
-    <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrófono en teclado de símbolos"</string>
+    <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro en teclado de símbolos"</string>
     <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 introducción"</string>
     <string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string>
@@ -120,25 +120,27 @@
     <string name="subtype_en_US" msgid="6160452336634534239">"inglés (EE.UU.)"</string>
     <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Inglés (Reino Unido) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Inglés (EE.UU.) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
-    <string name="subtype_no_language" msgid="141420857808801746">"ningún idioma"</string>
-    <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"ningún idioma (QWERTY)"</string>
-    <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"ningún idioma (QWERTZ)"</string>
-    <string name="subtype_no_language_azerty" msgid="8721460968141187394">"ningún idioma (AZERTY)"</string>
-    <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"ningún idioma (Dvorak)"</string>
-    <string name="subtype_no_language_colemak" msgid="4205992994906097244">"ningún idioma (Colemak)"</string>
-    <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"ningún idioma (PC)"</string>
+    <string name="subtype_no_language" msgid="141420857808801746">"Ningún idioma"</string>
+    <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"Ningún idioma (QWERTY)"</string>
+    <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"Ningún idioma (QWERTZ)"</string>
+    <string name="subtype_no_language_azerty" msgid="8721460968141187394">"Ningún idioma (AZERTY)"</string>
+    <string name="subtype_no_language_dvorak" msgid="3122976737669823935">"Ningún idioma (Dvorak)"</string>
+    <string name="subtype_no_language_colemak" msgid="4205992994906097244">"Ningún idioma (Colemak)"</string>
+    <string name="subtype_no_language_pcqwerty" msgid="8840928374394180189">"Ningún idioma (PC)"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos de entrada personalizados"</string>
     <string name="add_style" msgid="6163126614514489951">"Añadir estilo"</string>
     <string name="add" msgid="8299699805688017798">"Añadir"</string>
     <string name="remove" msgid="4486081658752944606">"Eliminar"</string>
     <string name="save" msgid="7646738597196767214">"Guardar"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
-    <string name="keyboard_layout_set" msgid="4309233698194565609">"Tipo"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Debes habilitar los estilos de entrada personalizados para usar un estilo personalizado. ¿Quieres hacerlo ahora?"</string>
-    <string name="enable" msgid="5031294444630523247">"Habilitar"</string>
-    <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">"Estudiar usabilidad"</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>
+    <string name="keyboard_layout_set" msgid="4309233698194565609">"Diseño"</string>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
+    <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudio de usabilidad"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Ajustes de duración de vibración al pulsar tecla"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volumen de sonido al pulsar tecla"</string>
 </resources>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index c4be52d..4c0da22 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Salvesta"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Keel"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Paigutus"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Kohandatud sisendi laad tuleb enne kasutamist lubada. Lubada?"</string>
-    <string name="enable" msgid="5031294444630523247">"Luba"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kasutatavuse uurimisrežiim"</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>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 98a6709..c791d0f 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -122,8 +122,8 @@
     <string name="keyboard_layout" msgid="8451164783510487501">"طرح زمینه صفحه کلید"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"انگیسی (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"انگیسی (US)"</string>
-    <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"انگلیسی (انگلستان) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
-    <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"انگلیسی (ایالات متحده) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"انگلیسی (انگلستان) ( <xliff:g id="LAYOUT">%s</xliff:g> )"</string>
+    <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"انگلیسی (ایالات متحده) ( <xliff:g id="LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_no_language" msgid="141420857808801746">"زبانی موجود نیست"</string>
     <string name="subtype_no_language_qwerty" msgid="2956121451616633133">"هیچ کدام از زبانها (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="1177848172397202890">"هیچکدام از زبان‌ها (QWERTZ)"</string>
@@ -138,10 +138,12 @@
     <string name="save" msgid="7646738597196767214">"ذخیره"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"زبان"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"چیدمان"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"سبک ورودی سفارشی شما باید قبل از شروع به استفاده از آن فعال شود. می‌خواهید اکنون آن را فعال کنید؟"</string>
-    <string name="enable" msgid="5031294444630523247">"فعال کردن"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"حالت بررسی قابلیت استفاده"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"تنظیمات مدت زمان لرزش فشار کلید"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"تنظیمات میزان صدای فشار کلید"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index e52896d..26858bb 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Tallenna"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Kieli"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Asettelu"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Ota muokattu syötetyyli käyttöön käyttääksesi sitä."</string>
-    <string name="enable" msgid="5031294444630523247">"Käyttöön"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Käytettävyystutkimustila"</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>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index c5f7d23..6c37aac 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Enregistrer"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Langue"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Clavier"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Vous devez activer votre style de saisie personnalisé avant de l\'utiliser. Voulez-vous le faire maintenant ?"</string>
-    <string name="enable" msgid="5031294444630523247">"Activer"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'étude de l\'utilisabilité"</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>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index b0a3bd5..f8808c8 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"सहेजें"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"भाषा"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"लेआउट"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"अपनी कस्‍टम इनपुट शैली का उपयोग शुरू करने से पहले उसे सक्षम करना होगा. उसे अभी सक्षम करना चाहते हैं?"</string>
-    <string name="enable" msgid="5031294444630523247">"सक्षम करें"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"उपयोगिता अध्ययन मोड"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"कुंजी-स्‍पर्श कंपन अवधि सेटिंग"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"कुंजी-स्‍पर्श ध्‍वनि वॉल्‍यूम सेटिंग"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 33cf28a..faeb108 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Spremi"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Jezik"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Izgled"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Prilagođeni stil unosa mora biti omogućen. Omogućiti sada?"</string>
-    <string name="enable" msgid="5031294444630523247">"Omogući"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način studije upotrebljivosti"</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>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 452da42..6732cbf 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Mentés"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Nyelv"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Elrendezés"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Az egyéni stílust először engedélyezni kell. Engedélyezi most?"</string>
-    <string name="enable" msgid="5031294444630523247">"Engedélyezés"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Használhatósági teszt"</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>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index d34a630..420474b 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Simpan"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Bahasa"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Tata Letak"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Gaya masukan khusus harus aktif sebelum digunakan. Aktifkan?"</string>
-    <string name="enable" msgid="5031294444630523247">"Aktifkan"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus studi daya guna"</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>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 84b1005..2100caa 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Salva"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Lingua"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Lo stile di ingresso personalizzato deve essere attivato prima dell\'utilizzo. Vuoi attivarlo?"</string>
-    <string name="enable" msgid="5031294444630523247">"Attiva"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modalità Studio sull\'usabilità"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Impostazioni durata vibrazione alla pressione di un tasto"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Impostazioni volume audio alla pressione di un tasto"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 329042a..764128f 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"שמור"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"שפה"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"פריסה"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"יש להפעיל את סגנון הקלט המותאם אישית לפני שתוכל להשתמש בו. האם אתה רוצה להפעיל אותו עכשיו?"</string>
-    <string name="enable" msgid="5031294444630523247">"הפעל"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"מצב מחקר שימושיות"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"הגדרות משך רטט בלחיצה על מקש"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"הגדרות עוצמת קול בלחיצה על מקש"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 5ffe2e4..8090eae 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"保存"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"言語"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"レイアウト"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"カスタム入力スタイルは、使用を開始する前に有効にする必要があります。今すぐ有効にしますか?"</string>
-    <string name="enable" msgid="5031294444630523247">"有効にする"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"使いやすさの研究モード"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"キー操作バイブの振動時間の設定"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"キー操作音の音量設定"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 06884a7..e1e01af 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"저장"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"언어"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"레이아웃"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"맞춤 입력 스타일을 사용하려면 사용 설정해야 합니다. 지금 사용 설정하시겠습니까?"</string>
-    <string name="enable" msgid="5031294444630523247">"사용"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"가용성 연구 모드"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"키를 누를 때 진동 시간 설정"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"키를 누를 때 효과음 설정"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 0b518ec..f2e3028 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Išsaugoti"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Kalba"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Išdėstymas"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Kad b. g. naud. tink. įv. stilių, reikia jį įg. Įgal. jį dabar?"</string>
-    <string name="enable" msgid="5031294444630523247">"Įgalinti"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tinkamumo tyrimo režimas"</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>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index b95dee3..785d208 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Saglabāt"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Valoda"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Izkārtojums"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Lai lietotu pielāgoto stilu, tas ir jāiespējo. Vai iespējot?"</string>
-    <string name="enable" msgid="5031294444630523247">"Iespējot"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Lietojamības izpētes režīms"</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>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index f0fe69c..da718a1 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Simpan"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Bahasa"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Reka Letak"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Gaya input tersuai anda perlu didayakan sebelum anda mula menggunakannya. Adakah anda ingin mendayakannya sekarang?"</string>
-    <string name="enable" msgid="5031294444630523247">"Dayakan"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mod kajian kebolehgunaan"</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>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 3ded50e..67c9114 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Lagre"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Språk"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Oppsett"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Tilpasset inndatastil må aktiveres før bruk. Vil du aktivere nå?"</string>
-    <string name="enable" msgid="5031294444630523247">"Aktiver"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Nyttighetsmodus"</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>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index eab47e6..d0507bc 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Opslaan"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Taal"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Lay-out"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"U moet uw aangepaste invoerstijl inschakelen voor u deze kunt gebruiken. Wilt u de invoerstijl nu inschakelen?"</string>
-    <string name="enable" msgid="5031294444630523247">"Inschakelen"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus voor gebruiksvriendelijkheidsonderzoek"</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>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index bd7d38f..c427339 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -24,10 +24,10 @@
     <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klawiatura Androida (AOSP)"</string>
     <string name="english_ime_settings" msgid="6661589557206947774">"Ustawienia klawiatury Android"</string>
     <string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string>
-    <string name="spell_checker_service_name" msgid="7338064335159755926">"Słownik Androida"</string>
+    <string name="spell_checker_service_name" msgid="7338064335159755926">"Sprawdzanie pisowni na Androidzie"</string>
     <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Sprawdzanie pisowni na Androidzie (AOSP)"</string>
     <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ustawienia sprawdzania pisowni"</string>
-    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj kontakty"</string>
+    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj nazwy kontaktów"</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>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Dźwięk przy naciśnięciu"</string>
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Zapisz"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Język"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Układ"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Niestandardowy styl wprowadzania trzeba przed użyciem włączyć. Zrobić to teraz?"</string>
-    <string name="enable" msgid="5031294444630523247">"Włącz"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tryb badania przydatności"</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>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index b964d1b..3e75440 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Guardar"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Esquema"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Tem de ativar o estilo de introdução personalizado antes de o usar. Quer ativar?"</string>
-    <string name="enable" msgid="5031294444630523247">"Ativar"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo da capacidade de utilização"</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>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 4f76c42..bd5a7d3 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -61,7 +61,7 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressivo"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muito agressivo"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestões p/ palavra seguinte"</string>
+    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestões para a palavra seguinte"</string>
     <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palavra anterior para melhorar as sugestões"</string>
     <string name="bigram_prediction" msgid="3216364899483135294">"Previsão da palavra seguinte"</string>
     <string name="bigram_prediction_summary" msgid="1747261921174300098">"Use também a palavra anterior para prever"</string>
@@ -134,11 +134,13 @@
     <string name="save" msgid="7646738597196767214">"Salvar"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Idioma"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Deseja ativar e usar o estilo de entrada personalizado?"</string>
-    <string name="enable" msgid="5031294444630523247">"Ativar"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo de utilização"</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>
+    <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Configurações do volume ao tocar a tecla"</string>
 </resources>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index c9a68d2..25897db 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -239,8 +239,6 @@
     <skip />
     <!-- no translation found for not_now (6172462888202790482) -->
     <skip />
-    <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
-    <skip />
     <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
     <skip />
     <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 070355e..9a98117 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Salvaţi"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Limbă"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Aspect"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Stilul de introducere personalizat trebuie să fie activat pentru a-l utiliza. Îl activaţi acum?"</string>
-    <string name="enable" msgid="5031294444630523247">"Activaţi"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modul Studiu privind utilizarea"</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>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index ad1f141..3f71cd1 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Сохранить"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Язык"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Раскладка"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Необходимо включить персонализированный стиль ввода."</string>
-    <string name="enable" msgid="5031294444630523247">"Включить"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим проверки удобства использования"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки вибросигнала при нажатии клавиш"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки громкости звука при нажатии клавиш"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index f9aa372..8115883 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Uložiť"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Jazyk"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Rozloženie"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Pred použitím vlastného štýlu vstupu ho musíte povoliť. Chcete ho povoliť?"</string>
-    <string name="enable" msgid="5031294444630523247">"Povoliť"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim štúdie použiteľnosti"</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>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index da3a87a..cf53da5 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Shrani"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Jezik"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Postavitev"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Slog vnosa po meri morate omogočiti. Ali ga želite omogočiti?"</string>
-    <string name="enable" msgid="5031294444630523247">"Omogoči"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način za preučevanje uporabnosti"</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>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 14ad0b3..9437047 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Сачувај"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Језик"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Распоред"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Прилагођени стил уноса треба да буде омогућен да бисте почели да га користите. Желите ли да га омогућите сада?"</string>
-    <string name="enable" msgid="5031294444630523247">"Омогући"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим за студију могућности коришћења"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Подешавања трајања вибрације при притиску на тастере"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Подешавања јачине звука при притиску на тастере"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 2e8f202..e8f63fd 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Spara"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Språk"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Din anpassade indatatyp måste aktiveras innan du börjar använda den. Vill du aktivera den nu?"</string>
-    <string name="enable" msgid="5031294444630523247">"Aktivera"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Läge för studie av användbarhet"</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>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index c57227d..adce194 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Hifadhi"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Lugha"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Mpangilio"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Unaweza kugeuza kukufaa mfumo wako ma maingizo ili kuwezeshwa kabla ya kuanza kuutumia. Unataka kuuwesha sasa?"</string>
-    <string name="enable" msgid="5031294444630523247">"Wezesha"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modi ya uchunguzi wa utumizi"</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>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index d8980f2..46bed17 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"บันทึก"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"ภาษา"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"การจัดวาง"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"ต้องเปิดใช้รูปแบบอินพุตที่กำหนดเองก่อน เปิดใช้เลยไหม"</string>
-    <string name="enable" msgid="5031294444630523247">"เปิดใช้งาน"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"โหมดศึกษาประโยชน์ในการใช้งาน"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"การตั้งค่าระยะเวลาการสั่นเมื่อกดแป้นพิมพ์"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"การตั้งค่าระดับเสียงเมื่อกดแป้นพิมพ์"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index 0932267..b0de5cf 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"I-save"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Wika"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Kailangan pinagana ang custom na istilo ng input bago simulang gamitin. Nais itong paganahin?"</string>
-    <string name="enable" msgid="5031294444630523247">"Paganahin"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Study mode ng pagiging kapaki-pakinabang"</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>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index a3428eb..7a2fc87 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Kaydet"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Dil"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Düzen"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Kullanmaya başlamadan önce özel giriş stilinizin etkinleştirilmesi gerekiyor. Şimdi etkinleştirmek ister misiniz?"</string>
-    <string name="enable" msgid="5031294444630523247">"Etkinleştir"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kullanılabilirlik çalışması modu"</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>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index bfaa78b..3667455 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Зберегти"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Мова"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Макет"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Щоб використовувати користувацький стиль введення, його потрібно ввімкнути. Увімкнути його?"</string>
-    <string name="enable" msgid="5031294444630523247">"Увімкнути"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим вивчення зручності у використанні"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Налаштування тривалості вібрації під час натискання клавіші"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Налаштування гучності звуку під час натискання клавіші"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index d11281b..5960824 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Lưu"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Ngôn ngữ"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Bố cục"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Bạn cần phải bật kiểu nhập tùy chỉnh trước khi bắt đầu sử dụng nó. Bạn có muốn bật kiểu nhập tùy chỉnh ngay bây giờ không?"</string>
-    <string name="enable" msgid="5031294444630523247">"Bật"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Chế độ nghiên cứu tính khả dụng"</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>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 06728cc..db1d701 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -29,9 +29,9 @@
     <string name="android_spell_checker_settings" msgid="5822324635435443689">"拼写检查设置"</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>
-    <string name="sound_on_keypress" msgid="6093592297198243644">"按键音效"</string>
-    <string name="popup_on_keypress" msgid="123894815723512944">"按键时弹出显示字符"</string>
+    <string name="vibrate_on_keypress" msgid="5258079494276955460">"按键时振动"</string>
+    <string name="sound_on_keypress" msgid="6093592297198243644">"按键时播放音效"</string>
+    <string name="popup_on_keypress" msgid="123894815723512944">"按键时显示弹出窗口"</string>
     <string name="general_category" msgid="1859088467017573195">"常规"</string>
     <string name="correction_category" msgid="2236750915056607613">"文本更正"</string>
     <string name="misc_category" msgid="6894192814868233453">"其他选项"</string>
@@ -40,10 +40,10 @@
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"切换到其他输入法"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"语言切换键也可用于切换其他输入法"</string>
     <string name="suppress_language_switch_key" msgid="8003788410354806368">"隐藏语言切换键"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"弹出字符隐藏延迟"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"关闭弹出键时的延迟"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"无延迟"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"默认"</string>
-    <string name="use_contacts_dict" msgid="4435317977804180815">"联系人姓名建议"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"推荐联系人姓名"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"使用联系人中的姓名提供建议和更正"</string>
     <string name="enable_span_insert" msgid="7204653105667167620">"允许再次更正"</string>
     <string name="enable_span_insert_summary" msgid="2947317657871394467">"设置建议以用于再次更正"</string>
@@ -53,7 +53,7 @@
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"显示更正建议"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"键入时显示建议的字词"</string>
     <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"始终显示"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"在纵向模式时显示"</string>
+    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"以纵向模式显示"</string>
     <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"始终隐藏"</string>
     <string name="auto_correction" msgid="4979925752001319458">"自动更正"</string>
     <string name="auto_correction_summary" msgid="5625751551134658006">"按空格键和标点可自动更正错别字"</string>
@@ -112,7 +112,7 @@
     <string name="language_selection_title" msgid="1651299598555326750">"输入语言"</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="has_dictionary" msgid="6071847973466625007">"提供字典"</string>
     <string name="prefs_enable_log" msgid="6620424505072963557">"启用用户反馈"</string>
     <string name="prefs_description_log" msgid="5827825607258246003">"自动向 Google 发送使用情况统计信息和崩溃报告,帮助改进该输入法编辑器。"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"键盘主题"</string>
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"保存"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"语言"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"布局"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"您需要先启用自定义输入样式,然后才能开始使用。要立即启用该样式吗?"</string>
-    <string name="enable" msgid="5031294444630523247">"启用"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"可用性研究模式"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"按键振动持续时间设置"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"按键音量设置"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 7997bd7..1e31040 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -58,13 +58,13 @@
     <string name="auto_correction" msgid="4979925752001319458">"自動修正"</string>
     <string name="auto_correction_summary" msgid="5625751551134658006">"按空白鍵或標點符號時,自動修正前面的錯字"</string>
     <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"關閉"</string>
-    <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"更正範圍小"</string>
-    <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"更正範圍大"</string>
+    <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"部分"</string>
+    <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"全部"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"更正範圍極大"</string>
     <string name="bigram_suggestion" msgid="8169311444438922902">"下一個字詞建議"</string>
     <string name="bigram_suggestion_summary" msgid="6635527607242625713">"根據前一個字詞找出更適合的建議"</string>
     <string name="bigram_prediction" msgid="3216364899483135294">"下一個字詞預測"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"同樣使用前一個字詞進行預測"</string>
+    <string name="bigram_prediction_summary" msgid="1747261921174300098">"同樣使用先前的字詞進行預測"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已儲存"</string>
     <string name="label_go_key" msgid="1635148082137219148">"開始"</string>
     <string name="label_next_key" msgid="362972844525672568">"繼續"</string>
@@ -133,12 +133,14 @@
     <string name="remove" msgid="4486081658752944606">"移除"</string>
     <string name="save" msgid="7646738597196767214">"儲存"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"語言"</string>
-    <string name="keyboard_layout_set" msgid="4309233698194565609">"配置"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"您必須先啟用自訂輸入樣式,才能開始使用。您要立即啟用嗎?"</string>
-    <string name="enable" msgid="5031294444630523247">"啟用"</string>
-    <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="keyboard_layout_set" msgid="4309233698194565609">"版面配置"</string>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
+    <string name="prefs_usability_study_mode" msgid="1261130555134595254">"使用性研究模式"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"按鍵震動持續時間設定"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"按鍵音量設定"</string>
 </resources>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 0032ead..1e87349 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -134,10 +134,12 @@
     <string name="save" msgid="7646738597196767214">"Londoloza"</string>
     <string name="subtype_locale" msgid="8576443440738143764">"Ulimi"</string>
     <string name="keyboard_layout_set" msgid="4309233698194565609">"Isakhiwo"</string>
-    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Isitayela sakho sokufakwayo sokwenza ngokwezifiso sidinga ukunikwa amandla ngaphambi kokusisebenzisa. Ufuna ukusinika amandla manje?"</string>
-    <string name="enable" msgid="5031294444630523247">"Nika amandla"</string>
-    <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>
+    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
+    <skip />
+    <!-- no translation found for enable (5031294444630523247) -->
+    <skip />
+    <!-- no translation found for not_now (6172462888202790482) -->
+    <skip />
     <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Imodi yesitadi yokusebenziseka"</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>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index d5268ea..e20061d 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -23,7 +23,8 @@
     <bool name="config_enable_show_voice_key_option">true</bool>
     <bool name="config_enable_show_popup_on_keypress_option">true</bool>
     <bool name="config_enable_next_word_suggestions_option">true</bool>
-    <bool name="config_enable_usability_study_mode_option">false</bool>
+    <!-- TODO: Disable the following configuration for production. -->
+    <bool name="config_enable_usability_study_mode_option">true</bool>
     <!-- Whether or not Popup on key press is enabled by default -->
     <bool name="config_default_popup_preview">true</bool>
     <!-- Default value for next word suggestion: while showing suggestions for a word should we weigh
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 0f8f6cd..20d8df7 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -240,10 +240,6 @@
                     + " ignoreModifier=" + ignoreModifierKey
                     + " enabled=" + key.isEnabled());
         }
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key,
-                    ignoreModifierKey);
-        }
         if (ignoreModifierKey) {
             return false;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 43ffb85..5aa9a08 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -305,9 +305,6 @@
             Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code)
                    + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this);
         }
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.keyboardState_onPressKey(code, this);
-        }
         if (code == Keyboard.CODE_SHIFT) {
             onPressShift();
         } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
@@ -341,9 +338,6 @@
             Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code)
                     + " sliding=" + withSliding + " " + this);
         }
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding);
-        }
         if (code == Keyboard.CODE_SHIFT) {
             onReleaseShift(withSliding);
         } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
@@ -375,9 +369,6 @@
         if (DEBUG_EVENT) {
             Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this);
         }
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.keyboardState_onLongPressTimeout(code, this);
-        }
         if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) {
             mLongPressShiftLockFired = true;
             mSwitchActions.hapticAndAudioFeedback(code);
@@ -509,9 +500,6 @@
         if (DEBUG_EVENT) {
             Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
         }
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this);
-        }
         // Switch back to the previous keyboard mode if the user cancels sliding input.
         if (isSinglePointer) {
             if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
@@ -543,9 +531,6 @@
                     + " single=" + isSinglePointer
                     + " autoCaps=" + autoCaps + " " + this);
         }
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this);
-        }
 
         switch (mSwitchState) {
         case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java
index 0f34d50..479b3bf 100644
--- a/java/src/com/android/inputmethod/latin/EditingUtils.java
+++ b/java/src/com/android/inputmethod/latin/EditingUtils.java
@@ -55,7 +55,7 @@
      */
     public static String getWordAtCursor(InputConnection connection, String separators) {
         // getWordRangeAtCursor returns null if the connection is null
-        Range r = getWordRangeAtCursor(connection, separators);
+        Range r = getWordRangeAtCursor(connection, separators, 0);
         return (r == null) ? null : r.mWord;
     }
 
@@ -85,7 +85,17 @@
         }
     }
 
-    private static Range getWordRangeAtCursor(InputConnection connection, String sep) {
+    /**
+     * Returns the text surrounding the cursor.
+     *
+     * @param connection the InputConnection to the TextView
+     * @param sep a string of characters that split words.
+     * @param additionalPrecedingWordsCount the number of words before the current word that should
+     *   be included in the returned range
+     * @return a range containing the text surrounding the cursor
+     */
+    public static Range getWordRangeAtCursor(InputConnection connection, String sep,
+            int additionalPrecedingWordsCount) {
         if (connection == null || sep == null) {
             return null;
         }
@@ -95,14 +105,40 @@
             return null;
         }
 
-        // Find first word separator before the cursor
+        // Going backward, alternate skipping non-separators and separators until enough words
+        // have been read.
         int start = before.length();
-        while (start > 0 && !isWhitespace(before.charAt(start - 1), sep)) start--;
+        boolean isStoppingAtWhitespace = true;  // toggles to indicate what to stop at
+        while (true) { // see comments below for why this is guaranteed to halt
+            while (start > 0) {
+                final int codePoint = Character.codePointBefore(before, start);
+                if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) {
+                    break;  // inner loop
+                }
+                --start;
+                if (Character.isSupplementaryCodePoint(codePoint)) {
+                    --start;
+                }
+            }
+            // isStoppingAtWhitespace is true every other time through the loop,
+            // so additionalPrecedingWordsCount is guaranteed to become < 0, which
+            // guarantees outer loop termination
+            if (isStoppingAtWhitespace && (--additionalPrecedingWordsCount < 0)) {
+                break;  // outer loop
+            }
+            isStoppingAtWhitespace = !isStoppingAtWhitespace;
+        }
 
         // Find last word separator after the cursor
         int end = -1;
-        while (++end < after.length() && !isWhitespace(after.charAt(end), sep)) {
-            // Nothing to do here.
+        while (++end < after.length()) {
+            final int codePoint = Character.codePointAt(after, end);
+            if (isSeparator(codePoint, sep)) {
+                break;
+            }
+            if (Character.isSupplementaryCodePoint(codePoint)) {
+                ++end;
+            }
         }
 
         int cursor = getCursorPosition(connection);
@@ -115,8 +151,8 @@
         return null;
     }
 
-    private static boolean isWhitespace(int code, String whitespace) {
-        return whitespace.contains(String.valueOf((char) code));
+    private static boolean isSeparator(int code, String sep) {
+        return sep.indexOf(code) != -1;
     }
 
     private static final Pattern spaceRegex = Pattern.compile("\\s+");
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 3854943..bd9a0c1 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -396,7 +396,7 @@
         mPrefs = prefs;
         LatinImeLogger.init(this, prefs);
         if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.init(this, prefs);
+            ResearchLogger.getInstance().init(this, prefs);
         }
         InputMethodManagerCompatWrapper.init(this);
         SubtypeSwitcher.init(this);
@@ -656,6 +656,7 @@
                     + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0));
         }
         if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.getInstance().start();
             ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs);
         }
         if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
@@ -735,6 +736,10 @@
 
     @Override
     public void onWindowHidden() {
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.latinIME_onWindowHidden(mLastSelectionStart, mLastSelectionEnd,
+                    getCurrentInputConnection());
+        }
         super.onWindowHidden();
         KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
         if (inputView != null) inputView.closing();
@@ -744,6 +749,9 @@
         super.onFinishInput();
 
         LatinImeLogger.commit();
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.getInstance().stop();
+        }
 
         KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
         if (inputView != null) inputView.closing();
@@ -764,7 +772,6 @@
             int composingSpanStart, int composingSpanEnd) {
         super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                 composingSpanStart, composingSpanEnd);
-
         if (DEBUG) {
             Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
                     + ", ose=" + oldSelEnd
@@ -776,9 +783,15 @@
                     + ", ce=" + composingSpanEnd);
         }
         if (ProductionFlag.IS_EXPERIMENTAL) {
+            final boolean expectingUpdateSelectionFromLogger =
+                    ResearchLogger.getAndClearLatinIMEExpectingUpdateSelection();
             ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd,
                     oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart,
-                    composingSpanEnd);
+                    composingSpanEnd, mExpectingUpdateSelection,
+                    expectingUpdateSelectionFromLogger, getCurrentInputConnection());
+            if (expectingUpdateSelectionFromLogger) {
+                return;
+            }
         }
 
         // TODO: refactor the following code to be less contrived.
@@ -1274,9 +1287,7 @@
         mLastKeyTime = when;
 
         if (ProductionFlag.IS_EXPERIMENTAL) {
-            if (ResearchLogger.sIsLogging) {
-                ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y);
-            }
+            ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
         }
 
         final KeyboardSwitcher switcher = mKeyboardSwitcher;
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index 66d6d58..e792d47 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -16,37 +16,42 @@
 
 package com.android.inputmethod.latin;
 
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+
 import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
 import android.inputmethodservice.InputMethodService;
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
 import android.os.SystemClock;
-import android.preference.PreferenceManager;
 import android.text.TextUtils;
+import android.util.JsonWriter;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.KeyDetector;
 import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.internal.KeyboardState;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.define.ProductionFlag;
 
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.charset.Charset;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
 import java.util.Map;
+import java.util.UUID;
 
 /**
  * Logs the use of the LatinIME keyboard.
@@ -58,373 +63,161 @@
  */
 public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = ResearchLogger.class.getSimpleName();
-    private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
     private static final boolean DEBUG = false;
+    /* package */ static boolean sIsLogging = false;
+    private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+    private static final String FILENAME_PREFIX = "researchLog";
+    private static final String FILENAME_SUFFIX = ".txt";
+    private static final JsonWriter NULL_JSON_WRITER = new JsonWriter(
+            new OutputStreamWriter(new NullOutputStream()));
+    private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
+            new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
 
-    private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager());
-    public static boolean sIsLogging = false;
-    /* package */ final Handler mLoggingHandler;
-    private InputMethodService mIms;
+    // constants related to specific log points
+    private static final String WHITESPACE_SEPARATORS = " \t\n\r";
+    private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
+    private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid";
 
-    /**
-     * Isolates management of files. This variable should never be null, but can be changed
-     * to support testing.
-     */
-    /* package */ LogFileManager mLogFileManager;
+    private static final ResearchLogger sInstance = new ResearchLogger();
+    private HandlerThread mHandlerThread;
+    /* package */ Handler mLoggingHandler;
+    // to write to a different filename, e.g., for testing, set mFile before calling start()
+    private File mFilesDir;
+    /* package */ File mFile;
+    private JsonWriter mJsonWriter = NULL_JSON_WRITER; // should never be null
 
-    /**
-     * Manages the file(s) that stores the logs.
-     *
-     * Handles creation, deletion, and provides Readers, Writers, and InputStreams to access
-     * the logs.
-     */
-    /* package */ static class LogFileManager {
-        public static final String RESEARCH_LOG_FILENAME_KEY = "RESEARCH_LOG_FILENAME";
+    private int mLoggingState;
+    private static final int LOGGING_STATE_OFF = 0;
+    private static final int LOGGING_STATE_ON = 1;
+    private static final int LOGGING_STATE_STOPPING = 2;
 
-        private static final String DEFAULT_FILENAME = "researchLog.txt";
-        private static final long LOGFILE_PURGE_INTERVAL = 1000 * 60 * 60 * 24;
+    // set when LatinIME should ignore an onUpdateSelection() callback that
+    // arises from operations in this class
+    private static boolean sLatinIMEExpectingUpdateSelection = false;
 
-        protected InputMethodService mIms;
-        protected File mFile;
-        protected PrintWriter mPrintWriter;
-
-        /* package */ LogFileManager() {
+    private static class NullOutputStream extends OutputStream {
+        /** {@inheritDoc} */
+        @Override
+        public void write(byte[] buffer, int offset, int count) throws IOException {
+            // nop
         }
 
-        public void init(final InputMethodService ims) {
-            mIms = ims;
+        /** {@inheritDoc} */
+        @Override
+        public void write(byte[] buffer) throws IOException {
+            // nop
         }
 
-        public synchronized void createLogFile() throws IOException {
-            createLogFile(DEFAULT_FILENAME);
-        }
-
-        public synchronized void createLogFile(final SharedPreferences prefs)
-                throws IOException {
-            final String filename =
-                    prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME);
-            createLogFile(filename);
-        }
-
-        public synchronized void createLogFile(final String filename)
-                throws IOException {
-            if (mIms == null) {
-                final String msg = "InputMethodService is not configured.  Logging is off.";
-                Log.w(TAG, msg);
-                throw new IOException(msg);
-            }
-            final File filesDir = mIms.getFilesDir();
-            if (filesDir == null || !filesDir.exists()) {
-                final String msg = "Storage directory does not exist.  Logging is off.";
-                Log.w(TAG, msg);
-                throw new IOException(msg);
-            }
-            close();
-            final File file = new File(filesDir, filename);
-            mFile = file;
-            boolean append = true;
-            if (file.exists() && file.lastModified() + LOGFILE_PURGE_INTERVAL <
-                    System.currentTimeMillis()) {
-                append = false;
-            }
-            mPrintWriter = new PrintWriter(new BufferedWriter(new FileWriter(file, append)), true);
-        }
-
-        public synchronized boolean append(final String s) {
-            PrintWriter printWriter = mPrintWriter;
-            if (printWriter == null || !mFile.exists()) {
-                if (DEBUG) {
-                    Log.w(TAG, "PrintWriter is null... attempting to create default log file");
-                }
-                try {
-                    createLogFile();
-                    printWriter = mPrintWriter;
-                } catch (IOException e) {
-                    Log.w(TAG, "Failed to create log file.  Not logging.");
-                    return false;
-                }
-            }
-            printWriter.print(s);
-            printWriter.flush();
-            return !printWriter.checkError();
-        }
-
-        public synchronized void reset() {
-            if (mPrintWriter != null) {
-                mPrintWriter.close();
-                mPrintWriter = null;
-                if (DEBUG) {
-                    Log.d(TAG, "logfile closed");
-                }
-            }
-            if (mFile != null) {
-                mFile.delete();
-                if (DEBUG) {
-                    Log.d(TAG, "logfile deleted");
-                }
-                mFile = null;
-            }
-        }
-
-        public synchronized void close() {
-            if (mPrintWriter != null) {
-                mPrintWriter.close();
-                mPrintWriter = null;
-                mFile = null;
-                if (DEBUG) {
-                    Log.d(TAG, "logfile closed");
-                }
-            }
-        }
-
-        /* package */ synchronized void flush() {
-            if (mPrintWriter != null) {
-                mPrintWriter.flush();
-            }
-        }
-
-        /* package */ synchronized String getContents() {
-            final File file = mFile;
-            if (file == null) {
-                return "";
-            }
-            if (mPrintWriter != null) {
-                mPrintWriter.flush();
-            }
-            FileInputStream stream = null;
-            FileChannel fileChannel = null;
-            String s = "";
-            try {
-                stream = new FileInputStream(file);
-                fileChannel = stream.getChannel();
-                final ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length());
-                fileChannel.read(byteBuffer);
-                byteBuffer.rewind();
-                CharBuffer charBuffer = Charset.defaultCharset().decode(byteBuffer);
-                s = charBuffer.toString();
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                try {
-                    if (fileChannel != null) {
-                        fileChannel.close();
-                    }
-                } catch (IOException e) {
-                    e.printStackTrace();
-                } finally {
-                    try {
-                        if (stream != null) {
-                            stream.close();
-                        }
-                    } catch (IOException e) {
-                        e.printStackTrace();
-                    }
-                }
-            }
-            return s;
+        @Override
+        public void write(int oneByte) {
         }
     }
 
-    private ResearchLogger(final LogFileManager logFileManager) {
-        final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task",
-                Process.THREAD_PRIORITY_BACKGROUND);
-        handlerThread.start();
-        mLoggingHandler = new Handler(handlerThread.getLooper());
-        mLogFileManager = logFileManager;
+    private ResearchLogger() {
+        mLoggingState = LOGGING_STATE_OFF;
     }
 
     public static ResearchLogger getInstance() {
         return sInstance;
     }
 
-    public static void init(final InputMethodService ims, final SharedPreferences prefs) {
-        sInstance.initInternal(ims, prefs);
-    }
-
-    /* package */ void initInternal(final InputMethodService ims, final SharedPreferences prefs) {
-        mIms = ims;
-        final LogFileManager logFileManager = mLogFileManager;
-        if (logFileManager != null) {
-            logFileManager.init(ims);
-            try {
-                logFileManager.createLogFile(prefs);
-            } catch (IOException e) {
-                e.printStackTrace();
+    public void init(final InputMethodService ims, final SharedPreferences prefs) {
+        assert ims != null;
+        if (ims == null) {
+            Log.w(TAG, "IMS is null; logging is off");
+        } else {
+            mFilesDir = ims.getFilesDir();
+            if (mFilesDir == null || !mFilesDir.exists()) {
+                Log.w(TAG, "IME storage directory does not exist.");
             }
         }
         if (prefs != null) {
             sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
-            prefs.registerOnSharedPreferenceChangeListener(this);
+            prefs.registerOnSharedPreferenceChangeListener(sInstance);
         }
     }
 
-    /**
-     * Represents a category of logging events that share the same subfield structure.
-     */
-    private static enum LogGroup {
-        MOTION_EVENT("m"),
-        KEY("k"),
-        CORRECTION("c"),
-        STATE_CHANGE("s"),
-        UNSTRUCTURED("u");
-
-        private final String mLogString;
-
-        private LogGroup(final String logString) {
-            mLogString = logString;
-        }
-    }
-
-    public void logMotionEvent(final int action, final long eventTime, final int id,
-            final int x, final int y, final float size, final float pressure) {
-        final String eventTag;
-        switch (action) {
-            case MotionEvent.ACTION_CANCEL: eventTag = "[Cancel]"; break;
-            case MotionEvent.ACTION_UP: eventTag = "[Up]"; break;
-            case MotionEvent.ACTION_DOWN: eventTag = "[Down]"; break;
-            case MotionEvent.ACTION_POINTER_UP: eventTag = "[PointerUp]"; break;
-            case MotionEvent.ACTION_POINTER_DOWN: eventTag = "[PointerDown]"; break;
-            case MotionEvent.ACTION_MOVE: eventTag = "[Move]"; break;
-            case MotionEvent.ACTION_OUTSIDE: eventTag = "[Outside]"; break;
-            default: eventTag = "[Action" + action + "]"; break;
-        }
-        if (!TextUtils.isEmpty(eventTag)) {
-            final StringBuilder sb = new StringBuilder();
-            sb.append(eventTag);
-            sb.append('\t'); sb.append(eventTime);
-            sb.append('\t'); sb.append(id);
-            sb.append('\t'); sb.append(x);
-            sb.append('\t'); sb.append(y);
-            sb.append('\t'); sb.append(size);
-            sb.append('\t'); sb.append(pressure);
-            write(LogGroup.MOTION_EVENT, sb.toString());
-        }
-    }
-
-    public void logKeyEvent(final int code, final int x, final int y) {
-        final StringBuilder sb = new StringBuilder();
-        sb.append(Keyboard.printableCode(code));
-        sb.append('\t'); sb.append(x);
-        sb.append('\t'); sb.append(y);
-        write(LogGroup.KEY, sb.toString());
-    }
-
-    public void logCorrection(final String subgroup, final String before, final String after,
-            final int position) {
-        final StringBuilder sb = new StringBuilder();
-        sb.append(subgroup);
-        sb.append('\t'); sb.append(before);
-        sb.append('\t'); sb.append(after);
-        sb.append('\t'); sb.append(position);
-        write(LogGroup.CORRECTION, sb.toString());
-    }
-
-    public void logStateChange(final String subgroup, final String details) {
-        write(LogGroup.STATE_CHANGE, subgroup + "\t" + details);
-    }
-
-    public static class UnsLogGroup {
-        private static final boolean DEFAULT_ENABLED = true;
-
-        private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED;
-        private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_COMMITTEXT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_PERFORMEDITORACTION_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_PICKSUGGESTIONMANUALLY_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_REVERTCOMMIT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean LATINIME_REVERTSWAPPUNCTUATION_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_SENDKEYCODEPOINT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED;
-        private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED = DEFAULT_ENABLED;
-        private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean
-                POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED;
-        private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED;
-        private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED
-                = DEFAULT_ENABLED;
-        private static final boolean SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED = DEFAULT_ENABLED;
-    }
-
-    public static void logUnstructured(String logGroup, final String details) {
-        // TODO: improve performance by making entire class static and/or implementing natively
-        getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details);
-    }
-
-    private void write(final LogGroup logGroup, final String log) {
-        // TODO: rewrite in native for better performance
-        mLoggingHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                final long currentTime = System.currentTimeMillis();
-                final long upTime = SystemClock.uptimeMillis();
-                final StringBuilder builder = new StringBuilder();
-                builder.append(currentTime);
-                builder.append('\t'); builder.append(upTime);
-                builder.append('\t'); builder.append(logGroup.mLogString);
-                builder.append('\t'); builder.append(log);
-                builder.append('\n');
-                if (DEBUG) {
-                    Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log);
+    public synchronized void start() {
+        Log.d(TAG, "start called");
+        if (mFilesDir == null || !mFilesDir.exists()) {
+            Log.w(TAG, "IME storage directory does not exist.  Cannot start logging.");
+        } else {
+            if (mHandlerThread == null || !mHandlerThread.isAlive()) {
+                mHandlerThread = new HandlerThread("ResearchLogger logging task",
+                        Process.THREAD_PRIORITY_BACKGROUND);
+                mHandlerThread.start();
+                mLoggingHandler = null;
+                mLoggingState = LOGGING_STATE_OFF;
+            }
+            if (mLoggingHandler == null) {
+                mLoggingHandler = new Handler(mHandlerThread.getLooper());
+                mLoggingState = LOGGING_STATE_OFF;
+            }
+            if (mFile == null) {
+                final String timestampString = TIMESTAMP_DATEFORMAT.format(new Date());
+                mFile = new File(mFilesDir, FILENAME_PREFIX + timestampString + FILENAME_SUFFIX);
+            }
+            if (mLoggingState == LOGGING_STATE_OFF) {
+                try {
+                    mJsonWriter = new JsonWriter(new BufferedWriter(new FileWriter(mFile)));
+                    mJsonWriter.setLenient(true);
+                    mJsonWriter.beginArray();
+                    mLoggingState = LOGGING_STATE_ON;
+                } catch (IOException e) {
+                    Log.w(TAG, "cannot start JsonWriter");
+                    mJsonWriter = NULL_JSON_WRITER;
+                    e.printStackTrace();
                 }
-                final String s = builder.toString();
-                if (mLogFileManager.append(s)) {
-                    // success
-                } else {
-                    if (DEBUG) {
-                        Log.w(TAG, "Unable to write to log.");
-                    }
-                    // perhaps logfile was deleted.  try to recreate and relog.
+            }
+        }
+    }
+
+    public synchronized void stop() {
+        Log.d(TAG, "stop called");
+        if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
+            mLoggingState = LOGGING_STATE_STOPPING;
+            // put this in the Handler queue so pending writes are processed first.
+            mLoggingHandler.post(new Runnable() {
+                @Override
+                public void run() {
                     try {
-                        mLogFileManager.createLogFile(PreferenceManager
-                                .getDefaultSharedPreferences(mIms));
-                        mLogFileManager.append(s);
+                        Log.d(TAG, "closing jsonwriter");
+                        mJsonWriter.endArray();
+                        mJsonWriter.flush();
+                        mJsonWriter.close();
+                    } catch (IllegalStateException e1) {
+                        // assume that this is just the json not being terminated properly.
+                        // ignore
+                        e1.printStackTrace();
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
+                    mJsonWriter = NULL_JSON_WRITER;
+                    mFile = null;
+                    mLoggingState = LOGGING_STATE_OFF;
+                    if (DEBUG) {
+                        Log.d(TAG, "logfile closed");
+                    }
+                    Log.d(TAG, "finished stop(), notifying");
+                    synchronized (ResearchLogger.this) {
+                        ResearchLogger.this.notify();
+                    }
                 }
+            });
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
             }
-        });
+        }
     }
 
-    public void clearAll() {
-        mLoggingHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                if (DEBUG) {
-                    Log.d(TAG, "Delete log file.");
-                }
-                mLogFileManager.reset();
-            }
-        });
-    }
-
-    /* package */ LogFileManager getLogFileManager() {
-        return mLogFileManager;
+    /* package */ synchronized void flush() {
+        try {
+            mJsonWriter.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
     }
 
     @Override
@@ -435,323 +228,533 @@
         sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
     }
 
-    public static void keyboardState_onCancelInput(final boolean isSinglePointer,
-            final KeyboardState keyboardState) {
-        if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) {
-            final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState;
-            logUnstructured("KeyboardState_onCancelInput", s);
+    private static final String CURRENT_TIME_KEY = "_ct";
+    private static final String UPTIME_KEY = "_ut";
+    private static final String EVENT_TYPE_KEY = "_ty";
+    private static final Object[] EVENTKEYS_NULLVALUES = {};
+
+    /**
+     * Write a description of the event out to the ResearchLog.
+     *
+     * Runs in the background to avoid blocking the UI thread.
+     *
+     * @param keys an array containing a descriptive name for the event, followed by the keys
+     * @param values an array of values, either a String or Number.  length should be one
+     * less than the keys array
+     */
+    private synchronized void writeEvent(final String[] keys, final Object[] values) {
+        assert values.length + 1 == keys.length;
+        if (mLoggingState == LOGGING_STATE_ON) {
+            mLoggingHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mJsonWriter.beginObject();
+                        mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
+                        mJsonWriter.name(UPTIME_KEY).value(SystemClock.uptimeMillis());
+                        mJsonWriter.name(EVENT_TYPE_KEY).value(keys[0]);
+                        final int length = values.length;
+                        for (int i = 0; i < length; i++) {
+                            mJsonWriter.name(keys[i + 1]);
+                            Object value = values[i];
+                            if (value instanceof String) {
+                                mJsonWriter.value((String) value);
+                            } else if (value instanceof Number) {
+                                mJsonWriter.value((Number) value);
+                            } else if (value instanceof Boolean) {
+                                mJsonWriter.value((Boolean) value);
+                            } else if (value instanceof CompletionInfo[]) {
+                                CompletionInfo[] ci = (CompletionInfo[]) value;
+                                mJsonWriter.beginArray();
+                                for (int j = 0; j < ci.length; j++) {
+                                    mJsonWriter.value(ci[j].toString());
+                                }
+                                mJsonWriter.endArray();
+                            } else if (value instanceof SharedPreferences) {
+                                SharedPreferences prefs = (SharedPreferences) value;
+                                mJsonWriter.beginObject();
+                                for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
+                                    mJsonWriter.name(entry.getKey());
+                                    final Object innerValue = entry.getValue();
+                                    if (innerValue == null) {
+                                        mJsonWriter.nullValue();
+                                    } else if (innerValue instanceof Boolean) {
+                                        mJsonWriter.value((Boolean) innerValue);
+                                    } else if (innerValue instanceof Number) {
+                                        mJsonWriter.value((Number) innerValue);
+                                    } else {
+                                        mJsonWriter.value(innerValue.toString());
+                                    }
+                                }
+                                mJsonWriter.endObject();
+                            } else if (value instanceof Key[]) {
+                                Key[] keys = (Key[]) value;
+                                mJsonWriter.beginArray();
+                                for (Key key : keys) {
+                                    mJsonWriter.beginObject();
+                                    mJsonWriter.name("code").value(key.mCode);
+                                    mJsonWriter.name("altCode").value(key.mAltCode);
+                                    mJsonWriter.name("x").value(key.mX);
+                                    mJsonWriter.name("y").value(key.mY);
+                                    mJsonWriter.name("w").value(key.mWidth);
+                                    mJsonWriter.name("h").value(key.mHeight);
+                                    mJsonWriter.endObject();
+                                }
+                                mJsonWriter.endArray();
+                            } else if (value instanceof SuggestedWords) {
+                                SuggestedWords words = (SuggestedWords) value;
+                                mJsonWriter.beginObject();
+                                mJsonWriter.name("typedWordValid").value(words.mTypedWordValid);
+                                mJsonWriter.name("hasAutoCorrectionCandidate")
+                                    .value(words.mHasAutoCorrectionCandidate);
+                                mJsonWriter.name("isPunctuationSuggestions")
+                                    .value(words.mIsPunctuationSuggestions);
+                                mJsonWriter.name("allowsToBeAutoCorrected")
+                                    .value(words.mAllowsToBeAutoCorrected);
+                                mJsonWriter.name("isObsoleteSuggestions")
+                                    .value(words.mIsObsoleteSuggestions);
+                                mJsonWriter.name("isPrediction")
+                                    .value(words.mIsPrediction);
+                                mJsonWriter.name("words");
+                                mJsonWriter.beginArray();
+                                final int size = words.size();
+                                for (int j = 0; j < size; j++) {
+                                    SuggestedWordInfo wordInfo = words.getWordInfo(j);
+                                    mJsonWriter.value(wordInfo.toString());
+                                }
+                                mJsonWriter.endArray();
+                                mJsonWriter.endObject();
+                            } else if (value == null) {
+                                mJsonWriter.nullValue();
+                            } else {
+                                Log.w(TAG, "Unrecognized type to be logged: " +
+                                        (value == null ? "<null>" : value.getClass().getName()));
+                                mJsonWriter.nullValue();
+                            }
+                        }
+                        mJsonWriter.endObject();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                        Log.w(TAG, "Error in JsonWriter; disabling logging");
+                        try {
+                            mJsonWriter.close();
+                        } catch (IllegalStateException e1) {
+                            // assume that this is just the json not being terminated properly.
+                            // ignore
+                        } catch (IOException e1) {
+                            e1.printStackTrace();
+                        } finally {
+                            mJsonWriter = NULL_JSON_WRITER;
+                        }
+                    }
+                }
+            });
         }
     }
 
-    public static void keyboardState_onCodeInput(
-            final int code, final boolean isSinglePointer, final int autoCaps,
-            final KeyboardState keyboardState) {
-        if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) {
-            final String s = "onCodeInput: code=" + Keyboard.printableCode(code)
-                    + " single=" + isSinglePointer
-                    + " autoCaps=" + autoCaps + " " + keyboardState;
-            logUnstructured("KeyboardState_onCodeInput", s);
+    private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = {
+        "LATINKEYBOARDVIEW_PROCESSMOTIONEVENT", "action", "eventTime", "id", "x", "y", "size",
+        "pressure"
+    };
+    public static void latinKeyboardView_processMotionEvent(final MotionEvent me, final int action,
+            final long eventTime, final int index, final int id, final int x, final int y) {
+        if (me != null) {
+            final String actionString;
+            switch (action) {
+                case MotionEvent.ACTION_CANCEL: actionString = "CANCEL"; break;
+                case MotionEvent.ACTION_UP: actionString = "UP"; break;
+                case MotionEvent.ACTION_DOWN: actionString = "DOWN"; break;
+                case MotionEvent.ACTION_POINTER_UP: actionString = "POINTER_UP"; break;
+                case MotionEvent.ACTION_POINTER_DOWN: actionString = "POINTER_DOWN"; break;
+                case MotionEvent.ACTION_MOVE: actionString = "MOVE"; break;
+                case MotionEvent.ACTION_OUTSIDE: actionString = "OUTSIDE"; break;
+                default: actionString = "ACTION_" + action; break;
+            }
+            final float size = me.getSize(index);
+            final float pressure = me.getPressure(index);
+            final Object[] values = {
+                actionString, eventTime, id, x, y, size, pressure
+            };
+            getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT, values);
         }
     }
 
-    public static void keyboardState_onLongPressTimeout(final int code,
-            final KeyboardState keyboardState) {
-        if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) {
-            final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " "
-                    + keyboardState;
-            logUnstructured("KeyboardState_onLongPressTimeout", s);
-        }
+    private static final String[] EVENTKEYS_LATINIME_ONCODEINPUT = {
+        "LATINIME_ONCODEINPUT", "code", "x", "y"
+    };
+    public static void latinIME_onCodeInput(final int code, final int x, final int y) {
+        final Object[] values = {
+            Keyboard.printableCode(code), x, y
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values);
     }
 
-    public static void keyboardState_onPressKey(final int code,
-            final KeyboardState keyboardState) {
-        if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) {
-            final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " "
-                    + keyboardState;
-            logUnstructured("KeyboardState_onPressKey", s);
-        }
+    private static final String[] EVENTKEYS_CORRECTION = {
+        "CORRECTION", "subgroup", "before", "after", "position"
+    };
+    public static void logCorrection(final String subgroup, final String before, final String after,
+            final int position) {
+        final Object[] values = {
+            subgroup, before, after, position
+        };
+        getInstance().writeEvent(EVENTKEYS_CORRECTION, values);
     }
 
-    public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code,
-            final boolean withSliding) {
-        if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) {
-            final String s = "onReleaseKey: code=" + Keyboard.printableCode(code)
-                    + " sliding=" + withSliding + " " + keyboardState;
-            logUnstructured("KeyboardState_onReleaseKey", s);
-        }
-    }
-
+    private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = {
+        "LATINIME_COMMITCURRENTAUTOCORRECTION", "typedWord", "autoCorrection"
+    };
     public static void latinIME_commitCurrentAutoCorrection(final String typedWord,
             final String autoCorrection) {
-        if (UnsLogGroup.LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED) {
-            if (typedWord.equals(autoCorrection)) {
-                getInstance().logCorrection("[----]", typedWord, autoCorrection, -1);
-            } else {
-                getInstance().logCorrection("[Auto]", typedWord, autoCorrection, -1);
-            }
-        }
+        final Object[] values = {
+            typedWord, autoCorrection
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = {
+        "LATINIME_COMMITTEXT", "typedWord"
+    };
     public static void latinIME_commitText(final CharSequence typedWord) {
-        if (UnsLogGroup.LATINIME_COMMITTEXT_ENABLED) {
-            logUnstructured("LatinIME_commitText", typedWord.toString());
-        }
+        final Object[] values = {
+            typedWord.toString()
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_COMMITTEXT, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = {
+        "LATINIME_DELETESURROUNDINGTEXT", "length"
+    };
     public static void latinIME_deleteSurroundingText(final int length) {
-        if (UnsLogGroup.LATINIME_DELETESURROUNDINGTEXT_ENABLED) {
-            logUnstructured("LatinIME_deleteSurroundingText", String.valueOf(length));
-        }
+        final Object[] values = {
+            length
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD = {
+        "LATINIME_DOUBLESPACEAUTOPERIOD"
+    };
     public static void latinIME_doubleSpaceAutoPeriod() {
-        if (UnsLogGroup.LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED) {
-            logUnstructured("LatinIME_doubleSpaceAutoPeriod", "");
-        }
+        getInstance().writeEvent(EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD, EVENTKEYS_NULLVALUES);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS = {
+        "LATINIME_ONDISPLAYCOMPLETIONS", "applicationSpecifiedCompletions"
+    };
     public static void latinIME_onDisplayCompletions(
             final CompletionInfo[] applicationSpecifiedCompletions) {
-        if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) {
-            final StringBuilder builder = new StringBuilder();
-            builder.append("Received completions:");
-            if (applicationSpecifiedCompletions != null) {
-                for (int i = 0; i < applicationSpecifiedCompletions.length; i++) {
-                    builder.append("  #");
-                    builder.append(i);
-                    builder.append(": ");
-                    builder.append(applicationSpecifiedCompletions[i]);
-                    builder.append("\n");
+        final Object[] values = {
+            applicationSpecifiedCompletions
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS, values);
+    }
+
+    /* package */ static boolean getAndClearLatinIMEExpectingUpdateSelection() {
+        boolean returnValue = sLatinIMEExpectingUpdateSelection;
+        sLatinIMEExpectingUpdateSelection = false;
+        return returnValue;
+    }
+
+    private static final String[] EVENTKEYS_LATINIME_ONWINDOWHIDDEN = {
+        "LATINIME_ONWINDOWHIDDEN", "isTextTruncated", "text"
+    };
+    public static void latinIME_onWindowHidden(final int savedSelectionStart,
+            final int savedSelectionEnd, final InputConnection ic) {
+        if (ic != null) {
+            ic.beginBatchEdit();
+            ic.performContextMenuAction(android.R.id.selectAll);
+            CharSequence charSequence = ic.getSelectedText(0);
+            ic.setSelection(savedSelectionStart, savedSelectionEnd);
+            ic.endBatchEdit();
+            sLatinIMEExpectingUpdateSelection = true;
+            Object[] values = new Object[2];
+            if (TextUtils.isEmpty(charSequence)) {
+                values[0] = false;
+                values[1] = "";
+            } else {
+                if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) {
+                    int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE;
+                    // do not cut in the middle of a supplementary character
+                    final char c = charSequence.charAt(length - 1);
+                    if (Character.isHighSurrogate(c)) {
+                        length--;
+                    }
+                    final CharSequence truncatedCharSequence = charSequence.subSequence(0, length);
+                    values[0] = true;
+                    values[1] = truncatedCharSequence.toString();
+                } else {
+                    values[0] = false;
+                    values[1] = charSequence.toString();
                 }
             }
-            logUnstructured("LatinIME_onDisplayCompletions", builder.toString());
+            getInstance().writeEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values);
         }
     }
 
+    private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = {
+        "LATINIME_ONSTARTINPUTVIEWINTERNAL", "uuid", "packageName", "inputType", "imeOptions",
+        "fieldId", "display", "model", "prefs"
+    };
+
     public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
             final SharedPreferences prefs) {
-        if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) {
-            final StringBuilder builder = new StringBuilder();
-            builder.append("onStartInputView: editorInfo:");
-            builder.append("\tinputType=");
-            builder.append(Integer.toHexString(editorInfo.inputType));
-            builder.append("\timeOptions=");
-            builder.append(Integer.toHexString(editorInfo.imeOptions));
-            builder.append("\tdisplay="); builder.append(Build.DISPLAY);
-            builder.append("\tmodel="); builder.append(Build.MODEL);
-            for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
-                builder.append("\t" + entry.getKey());
-                Object value = entry.getValue();
-                builder.append("=" + ((value == null) ? "<null>" : value.toString()));
-            }
-            logUnstructured("LatinIME_onStartInputViewInternal", builder.toString());
+        if (editorInfo != null) {
+            final Object[] values = {
+                getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
+                Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId, Build.DISPLAY,
+                Build.MODEL, prefs
+            };
+            getInstance().writeEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values);
         }
     }
 
+    private static String getUUID(final SharedPreferences prefs) {
+        String uuidString = prefs.getString(PREF_RESEARCH_LOGGER_UUID_STRING, null);
+        if (null == uuidString) {
+            UUID uuid = UUID.randomUUID();
+            uuidString = uuid.toString();
+            Editor editor = prefs.edit();
+            editor.putString(PREF_RESEARCH_LOGGER_UUID_STRING, uuidString);
+            editor.apply();
+        }
+        return uuidString;
+    }
+
+    private static final String[] EVENTKEYS_LATINIME_ONUPDATESELECTION = {
+        "LATINIME_ONUPDATESELECTION", "lastSelectionStart", "lastSelectionEnd", "oldSelStart",
+        "oldSelEnd", "newSelStart", "newSelEnd", "composingSpanStart", "composingSpanEnd",
+        "expectingUpdateSelection", "expectingUpdateSelectionFromLogger", "context"
+    };
+
     public static void latinIME_onUpdateSelection(final int lastSelectionStart,
             final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd,
             final int newSelStart, final int newSelEnd, final int composingSpanStart,
-            final int composingSpanEnd) {
-        if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) {
-            final String s = "onUpdateSelection: oss=" + oldSelStart
-                    + ", ose=" + oldSelEnd
-                    + ", lss=" + lastSelectionStart
-                    + ", lse=" + lastSelectionEnd
-                    + ", nss=" + newSelStart
-                    + ", nse=" + newSelEnd
-                    + ", cs=" + composingSpanStart
-                    + ", ce=" + composingSpanEnd;
-            logUnstructured("LatinIME_onUpdateSelection", s);
-        }
+            final int composingSpanEnd, final boolean expectingUpdateSelection,
+            final boolean expectingUpdateSelectionFromLogger, final InputConnection connection) {
+        final Object[] values = {
+            lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart,
+            newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection,
+            expectingUpdateSelectionFromLogger,
+            EditingUtils.getWordRangeAtCursor(connection, WHITESPACE_SEPARATORS, 1).mWord
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_PERFORMEDITORACTION = {
+        "LATINIME_PERFORMEDITORACTION", "imeActionNext"
+    };
     public static void latinIME_performEditorAction(final int imeActionNext) {
-        if (UnsLogGroup.LATINIME_PERFORMEDITORACTION_ENABLED) {
-            logUnstructured("LatinIME_performEditorAction", String.valueOf(imeActionNext));
-        }
+        final Object[] values = {
+            imeActionNext
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_PERFORMEDITORACTION, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION = {
+        "LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION", "index", "text", "x", "y"
+    };
     public static void latinIME_pickApplicationSpecifiedCompletion(final int index,
             final CharSequence text, int x, int y) {
-        if (UnsLogGroup.LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED) {
-            final String s = String.valueOf(index) + '\t' + text + '\t' + x + '\t' + y;
-            logUnstructured("LatinIME_pickApplicationSpecifiedCompletion", s);
-        }
+        final Object[] values = {
+            index, text.toString(), x, y
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = {
+        "LATINIME_PICKSUGGESTIONMANUALLY", "replacedWord", "index", "suggestion", "x", "y"
+    };
     public static void latinIME_pickSuggestionManually(final String replacedWord,
             final int index, CharSequence suggestion, int x, int y) {
-        if (UnsLogGroup.LATINIME_PICKSUGGESTIONMANUALLY_ENABLED) {
-            final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y;
-            logUnstructured("LatinIME_pickSuggestionManually", s);
-        }
+        final Object[] values = {
+            replacedWord, index, suggestion.toString(), x, y
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = {
+        "LATINIME_PUNCTUATIONSUGGESTION", "index", "suggestion", "x", "y"
+    };
     public static void latinIME_punctuationSuggestion(final int index,
             final CharSequence suggestion, int x, int y) {
-        if (UnsLogGroup.LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED) {
-            final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y;
-            logUnstructured("LatinIME_pickPunctuationSuggestion", s);
-        }
+        final Object[] values = {
+            index, suggestion.toString(), x, y
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT = {
+        "LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT"
+    };
     public static void latinIME_revertDoubleSpaceWhileInBatchEdit() {
-        if (UnsLogGroup.LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED) {
-            logUnstructured("LatinIME_revertDoubleSpaceWhileInBatchEdit", "");
-        }
+        getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT,
+                EVENTKEYS_NULLVALUES);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION = {
+        "LATINIME_REVERTSWAPPUNCTUATION"
+    };
     public static void latinIME_revertSwapPunctuation() {
-        if (UnsLogGroup.LATINIME_REVERTSWAPPUNCTUATION_ENABLED) {
-            logUnstructured("LatinIME_revertSwapPunctuation", "");
-        }
+        getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION, EVENTKEYS_NULLVALUES);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_SENDKEYCODEPOINT = {
+        "LATINIME_SENDKEYCODEPOINT", "code"
+    };
     public static void latinIME_sendKeyCodePoint(final int code) {
-        if (UnsLogGroup.LATINIME_SENDKEYCODEPOINT_ENABLED) {
-            logUnstructured("LatinIME_sendKeyCodePoint", String.valueOf(code));
-        }
+        final Object[] values = {
+            code
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT = {
+        "LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT"
+    };
     public static void latinIME_swapSwapperAndSpaceWhileInBatchEdit() {
-        if (UnsLogGroup.LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED) {
-            logUnstructured("latinIME_swapSwapperAndSpaceWhileInBatchEdit", "");
-        }
+        getInstance().writeEvent(EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT,
+                EVENTKEYS_NULLVALUES);
     }
 
+    private static final String[] EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW = {
+        "LATINIME_SWITCHTOKEYBOARDVIEW"
+    };
     public static void latinIME_switchToKeyboardView() {
-        if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) {
-            final String s = "Switch to keyboard view.";
-            logUnstructured("LatinIME_switchToKeyboardView", s);
-        }
+        getInstance().writeEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES);
     }
 
+    private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = {
+        "LATINKEYBOARDVIEW_ONLONGPRESS"
+    };
     public static void latinKeyboardView_onLongPress() {
-        if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) {
-            final String s = "long press detected";
-            logUnstructured("LatinKeyboardView_onLongPress", s);
-        }
+        getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS, EVENTKEYS_NULLVALUES);
     }
 
-    public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action,
-            long eventTime, int index, int id, int x, int y) {
-        if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) {
-            final float size = me.getSize(index);
-            final float pressure = me.getPressure(index);
-            if (action != MotionEvent.ACTION_MOVE) {
-                getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure);
-            }
-        }
-    }
-
+    private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = {
+        "LATINKEYBOARDVIEW_SETKEYBOARD", "elementId", "locale", "orientation", "width",
+        "modeName", "action", "navigateNext", "navigatePrevious", "clobberSettingsKey",
+        "passwordInput", "shortcutKeyEnabled", "hasShortcutKey", "languageSwitchKeyEnabled",
+        "isMultiLine", "tw", "th", "keys"
+    };
     public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) {
-        if (UnsLogGroup.LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED) {
-            StringBuilder builder = new StringBuilder();
-            builder.append("id=");
-            builder.append(keyboard.mId);
-            builder.append("\tw=");
-            builder.append(keyboard.mOccupiedWidth);
-            builder.append("\th=");
-            builder.append(keyboard.mOccupiedHeight);
-            builder.append("\tkeys=[");
-            boolean first = true;
-            for (Key key : keyboard.mKeys) {
-                if (first) {
-                    first = false;
-                } else {
-                    builder.append(",");
-                }
-                builder.append("{code:");
-                builder.append(key.mCode);
-                builder.append(",altCode:");
-                builder.append(key.mAltCode);
-                builder.append(",x:");
-                builder.append(key.mX);
-                builder.append(",y:");
-                builder.append(key.mY);
-                builder.append(",w:");
-                builder.append(key.mWidth);
-                builder.append(",h:");
-                builder.append(key.mHeight);
-                builder.append("}");
-            }
-            builder.append("]");
-            logUnstructured("LatinKeyboardView_setKeyboard", builder.toString());
+        if (keyboard != null) {
+            final KeyboardId kid = keyboard.mId;
+            final Object[] values = {
+                    KeyboardId.elementIdToName(kid.mElementId),
+                    kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
+                    kid.mOrientation,
+                    kid.mWidth,
+                    KeyboardId.modeName(kid.mMode),
+                    kid.imeAction(),
+                    kid.navigateNext(),
+                    kid.navigatePrevious(),
+                    kid.mClobberSettingsKey,
+                    kid.passwordInput(),
+                    kid.mShortcutKeyEnabled,
+                    kid.mHasShortcutKey,
+                    kid.mLanguageSwitchKeyEnabled,
+                    kid.isMultiLine(),
+                    keyboard.mOccupiedWidth,
+                    keyboard.mOccupiedHeight,
+                    keyboard.mKeys
+                };
+            getInstance().writeEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values);
         }
     }
 
+    private static final String[] EVENTKEYS_LATINIME_REVERTCOMMIT = {
+        "LATINIME_REVERTCOMMIT", "originallyTypedWord"
+    };
     public static void latinIME_revertCommit(final String originallyTypedWord) {
-        if (UnsLogGroup.LATINIME_REVERTCOMMIT_ENABLED) {
-            logUnstructured("LatinIME_revertCommit", originallyTypedWord);
-        }
+        final Object[] values = {
+            originallyTypedWord
+        };
+        getInstance().writeEvent(EVENTKEYS_LATINIME_REVERTCOMMIT, values);
     }
 
+    private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT = {
+        "POINTERTRACKER_CALLLISTENERONCANCELINPUT"
+    };
     public static void pointerTracker_callListenerOnCancelInput() {
-        final String s = "onCancelInput";
-        if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) {
-            logUnstructured("PointerTracker_callListenerOnCancelInput", s);
-        }
+        getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT,
+                EVENTKEYS_NULLVALUES);
     }
 
+    private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT = {
+        "POINTERTRACKER_CALLLISTENERONCODEINPUT", "code", "outputText", "x", "y",
+        "ignoreModifierKey", "altersCode", "isEnabled"
+    };
     public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x,
             final int y, final boolean ignoreModifierKey, final boolean altersCode,
             final int code) {
-        if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) {
-            final String s = "onCodeInput: " + Keyboard.printableCode(code)
-                    + " text=" + key.mOutputText + " x=" + x + " y=" + y
-                    + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode
-                    + " enabled=" + key.isEnabled();
-            logUnstructured("PointerTracker_callListenerOnCodeInput", s);
+        if (key != null) {
+            CharSequence outputText = key.mOutputText;
+            final Object[] values = {
+                Keyboard.printableCode(code), outputText == null ? "" : outputText.toString(),
+                x, y, ignoreModifierKey, altersCode, key.isEnabled()
+            };
+            getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values);
         }
     }
 
-    public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(
-            final Key key, final boolean ignoreModifierKey) {
-        if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) {
-            final String s = "onPress    : " + KeyDetector.printableCode(key)
-                    + " ignoreModifier=" + ignoreModifierKey
-                    + " enabled=" + key.isEnabled();
-            logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s);
-        }
-    }
-
+    private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = {
+        "POINTERTRACKER_CALLLISTENERONRELEASE", "code", "withSliding", "ignoreModifierKey",
+        "isEnabled"
+    };
     public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode,
             final boolean withSliding, final boolean ignoreModifierKey) {
-        if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) {
-            final String s = "onRelease  : " + Keyboard.printableCode(primaryCode)
-                    + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey
-                    + " enabled="+ key.isEnabled();
-            logUnstructured("PointerTracker_callListenerOnRelease", s);
+        if (key != null) {
+            final Object[] values = {
+                Keyboard.printableCode(primaryCode), withSliding, ignoreModifierKey,
+                key.isEnabled()
+            };
+            getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE, values);
         }
     }
 
+    private static final String[] EVENTKEYS_POINTERTRACKER_ONDOWNEVENT = {
+        "POINTERTRACKER_ONDOWNEVENT", "deltaT", "distanceSquared"
+    };
     public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) {
-        if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) {
-            final String s = "onDownEvent: ignore potential noise: time=" + deltaT
-                    + " distance=" + distanceSquared;
-            logUnstructured("PointerTracker_onDownEvent", s);
-        }
+        final Object[] values = {
+            deltaT, distanceSquared
+        };
+        getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_ONDOWNEVENT, values);
     }
 
+    private static final String[] EVENTKEYS_POINTERTRACKER_ONMOVEEVENT = {
+        "POINTERTRACKER_ONMOVEEVENT", "x", "y", "lastX", "lastY"
+    };
     public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX,
             final int lastY) {
-        if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) {
-            final String s = String.format("onMoveEvent: sudden move is translated to "
-                    + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y);
-            logUnstructured("PointerTracker_onMoveEvent", s);
-        }
+        final Object[] values = {
+            x, y, lastX, lastY
+        };
+        getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_ONMOVEEVENT, values);
     }
 
+    private static final String[] EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT = {
+        "SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT", "motionEvent"
+    };
     public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) {
-        if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) {
-            final String s = "onTouchEvent: ignore sudden jump " + me;
-            logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s);
+        if (me != null) {
+            final Object[] values = {
+                me.toString()
+            };
+            getInstance().writeEvent(EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT,
+                    values);
         }
     }
 
-    public static void suggestionsView_setSuggestions(final SuggestedWords mSuggestedWords) {
-        if (UnsLogGroup.SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED) {
-            logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString());
+    private static final String[] EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS = {
+        "SUGGESTIONSVIEW_SETSUGGESTIONS", "suggestedWords"
+    };
+    public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) {
+        if (suggestedWords != null) {
+            final Object[] values = {
+                suggestedWords
+            };
+            getInstance().writeEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS, values);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java b/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java
new file mode 100644
index 0000000..c73f889
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/EditingUtilsTests.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.test.AndroidTestCase;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputConnectionWrapper;
+
+import com.android.inputmethod.latin.EditingUtils.Range;
+
+public class EditingUtilsTests extends AndroidTestCase {
+
+    // The following is meant to be a reasonable default for
+    // the "word_separators" resource.
+    private static final String sSeparators = ".,:;!?-";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    private class MockConnection extends InputConnectionWrapper {
+        final String mTextBefore;
+        final String mTextAfter;
+        final ExtractedText mExtractedText;
+
+        public MockConnection(String textBefore, String textAfter, ExtractedText extractedText) {
+            super(null, false);
+            mTextBefore = textBefore;
+            mTextAfter = textAfter;
+            mExtractedText = extractedText;
+        }
+
+        /* (non-Javadoc)
+         * @see android.view.inputmethod.InputConnectionWrapper#getTextBeforeCursor(int, int)
+         */
+        @Override
+        public CharSequence getTextBeforeCursor(int n, int flags) {
+            return mTextBefore;
+        }
+
+        /* (non-Javadoc)
+         * @see android.view.inputmethod.InputConnectionWrapper#getTextAfterCursor(int, int)
+         */
+        @Override
+        public CharSequence getTextAfterCursor(int n, int flags) {
+            return mTextAfter;
+        }
+
+        /* (non-Javadoc)
+         * @see android.view.inputmethod.InputConnectionWrapper#getExtractedText(ExtractedTextRequest, int)
+         */
+        @Override
+        public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
+            return mExtractedText;
+        }
+    }
+
+    /************************** Tests ************************/
+
+    /**
+     * Test for getting previous word (for bigram suggestions)
+     */
+    public void testGetPreviousWord() {
+        // If one of the following cases breaks, the bigram suggestions won't work.
+        assertEquals(EditingUtils.getPreviousWord("abc def", sSeparators), "abc");
+        assertNull(EditingUtils.getPreviousWord("abc", sSeparators));
+        assertNull(EditingUtils.getPreviousWord("abc. def", sSeparators));
+
+        // The following tests reflect the current behavior of the function
+        // EditingUtils#getPreviousWord.
+        // TODO: However at this time, the code does never go
+        // into such a path, so it should be safe to change the behavior of
+        // this function if needed - especially since it does not seem very
+        // logical. These tests are just there to catch any unintentional
+        // changes in the behavior of the EditingUtils#getPreviousWord method.
+        assertEquals(EditingUtils.getPreviousWord("abc def ", sSeparators), "abc");
+        assertEquals(EditingUtils.getPreviousWord("abc def.", sSeparators), "abc");
+        assertEquals(EditingUtils.getPreviousWord("abc def .", sSeparators), "def");
+        assertNull(EditingUtils.getPreviousWord("abc ", sSeparators));
+    }
+
+    /**
+     * Test for getting the word before the cursor (for bigram)
+     */
+    public void testGetThisWord() {
+        assertEquals(EditingUtils.getThisWord("abc def", sSeparators), "def");
+        assertEquals(EditingUtils.getThisWord("abc def ", sSeparators), "def");
+        assertNull(EditingUtils.getThisWord("abc def.", sSeparators));
+        assertNull(EditingUtils.getThisWord("abc def .", sSeparators));
+    }
+
+    /**
+     * Test logic in getting the word range at the cursor.
+     */
+    public void testGetWordRangeAtCursor() {
+        ExtractedText et = new ExtractedText();
+        InputConnection mockConnection;
+        mockConnection = new MockConnection("word wo", "rd", et);
+        et.startOffset = 0;
+        et.selectionStart = 7;
+        Range r;
+
+        // basic case
+        r = EditingUtils.getWordRangeAtCursor(mockConnection, " ", 0);
+        assertEquals("word", r.mWord);
+        r = null;
+
+        // more than one word
+        r = EditingUtils.getWordRangeAtCursor(mockConnection, " ", 1);
+        assertEquals("word word", r.mWord);
+        r = null;
+
+        // tab character instead of space
+        mockConnection = new MockConnection("one\tword\two", "rd", et);
+        r = EditingUtils.getWordRangeAtCursor(mockConnection, "\t", 1);
+        assertEquals("word\tword", r.mWord);
+        r = null;
+
+        // only one word doesn't go too far
+        mockConnection = new MockConnection("one\tword\two", "rd", et);
+        r = EditingUtils.getWordRangeAtCursor(mockConnection, "\t", 1);
+        assertEquals("word\tword", r.mWord);
+        r = null;
+
+        // tab or space
+        mockConnection = new MockConnection("one word\two", "rd", et);
+        r = EditingUtils.getWordRangeAtCursor(mockConnection, " \t", 1);
+        assertEquals("word\tword", r.mWord);
+        r = null;
+
+        // tab or space multiword
+        mockConnection = new MockConnection("one word\two", "rd", et);
+        r = EditingUtils.getWordRangeAtCursor(mockConnection, " \t", 2);
+        assertEquals("one word\tword", r.mWord);
+        r = null;
+
+        // splitting on supplementary character
+        final String supplementaryChar = "\uD840\uDC8A";
+        mockConnection = new MockConnection("one word" + supplementaryChar + "wo", "rd", et);
+        r = EditingUtils.getWordRangeAtCursor(mockConnection, supplementaryChar, 0);
+        assertEquals("word", r.mWord);
+        r = null;
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/UtilsTests.java b/tests/src/com/android/inputmethod/latin/UtilsTests.java
deleted file mode 100644
index 2ef4e2f..0000000
--- a/tests/src/com/android/inputmethod/latin/UtilsTests.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010,2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.test.AndroidTestCase;
-
-public class UtilsTests extends AndroidTestCase {
-
-    // The following is meant to be a reasonable default for
-    // the "word_separators" resource.
-    private static final String sSeparators = ".,:;!?-";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    /************************** Tests ************************/
-
-    /**
-     * Test for getting previous word (for bigram suggestions)
-     */
-    public void testGetPreviousWord() {
-        // If one of the following cases breaks, the bigram suggestions won't work.
-        assertEquals(EditingUtils.getPreviousWord("abc def", sSeparators), "abc");
-        assertNull(EditingUtils.getPreviousWord("abc", sSeparators));
-        assertNull(EditingUtils.getPreviousWord("abc. def", sSeparators));
-
-        // The following tests reflect the current behavior of the function
-        // EditingUtils#getPreviousWord.
-        // TODO: However at this time, the code does never go
-        // into such a path, so it should be safe to change the behavior of
-        // this function if needed - especially since it does not seem very
-        // logical. These tests are just there to catch any unintentional
-        // changes in the behavior of the EditingUtils#getPreviousWord method.
-        assertEquals(EditingUtils.getPreviousWord("abc def ", sSeparators), "abc");
-        assertEquals(EditingUtils.getPreviousWord("abc def.", sSeparators), "abc");
-        assertEquals(EditingUtils.getPreviousWord("abc def .", sSeparators), "def");
-        assertNull(EditingUtils.getPreviousWord("abc ", sSeparators));
-    }
-
-    /**
-     * Test for getting the word before the cursor (for bigram)
-     */
-    public void testGetThisWord() {
-        assertEquals(EditingUtils.getThisWord("abc def", sSeparators), "def");
-        assertEquals(EditingUtils.getThisWord("abc def ", sSeparators), "def");
-        assertNull(EditingUtils.getThisWord("abc def.", sSeparators));
-        assertNull(EditingUtils.getThisWord("abc def .", sSeparators));
-    }
-}
diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk
new file mode 100644
index 0000000..9e8dbe0
--- /dev/null
+++ b/tools/dicttool/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_JAR_MANIFEST := etc/manifest.txt
+LOCAL_MODULE := dicttool
+LOCAL_MODULE_TAGS := eng
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+include $(LOCAL_PATH)/etc/Android.mk
diff --git a/tools/dicttool/etc/Android.mk b/tools/dicttool/etc/Android.mk
new file mode 100644
index 0000000..03d4a96
--- /dev/null
+++ b/tools/dicttool/etc/Android.mk
@@ -0,0 +1,20 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng
+LOCAL_PREBUILT_EXECUTABLES := dicttool
+include $(BUILD_HOST_PREBUILT)
diff --git a/tools/dicttool/etc/dicttool b/tools/dicttool/etc/dicttool
new file mode 100755
index 0000000..8a39694
--- /dev/null
+++ b/tools/dicttool/etc/dicttool
@@ -0,0 +1,62 @@
+#!/bin/sh
+# Copyright 2011, 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=dicttool.jar
+frameworkdir="$progdir"
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+    frameworkdir=`dirname "$progdir"`/tools/lib
+    libdir=`dirname "$progdir"`/tools/lib
+fi
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+    frameworkdir=`dirname "$progdir"`/framework
+    libdir=`dirname "$progdir"`/lib
+fi
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+    echo `basename "$prog"`": can't find $jarfile"
+    exit 1
+fi
+
+if [ "$OSTYPE" = "cygwin" ] ; then
+    jarpath=`cygpath -w  "$frameworkdir/$jarfile"`
+    progdir=`cygpath -w  "$progdir"`
+else
+    jarpath="$frameworkdir/$jarfile"
+fi
+
+# might need more memory, e.g. -Xmx128M
+exec java -ea -jar "$jarpath" "$@"
diff --git a/tools/dicttool/etc/manifest.txt b/tools/dicttool/etc/manifest.txt
new file mode 100644
index 0000000..67c8521
--- /dev/null
+++ b/tools/dicttool/etc/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.inputmethod.latin.dicttool.Dicttool
diff --git a/tools/dicttool/src/android/inputmethod/latin/dicttool/Compress.java b/tools/dicttool/src/android/inputmethod/latin/dicttool/Compress.java
new file mode 100644
index 0000000..307f596
--- /dev/null
+++ b/tools/dicttool/src/android/inputmethod/latin/dicttool/Compress.java
@@ -0,0 +1,94 @@
+/**
+ * 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.
+ */
+
+package com.android.inputmethod.latin.dicttool;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+public class Compress {
+
+    private static OutputStream getCompressedStream(final OutputStream out)
+        throws java.io.IOException {
+        return new GZIPOutputStream(out);
+    }
+
+    private static InputStream getUncompressedStream(final InputStream in) throws IOException {
+        return new GZIPInputStream(in);
+    }
+
+    public static void copy(final InputStream input, final OutputStream output) throws IOException {
+        final byte[] buffer = new byte[1000];
+        for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer))
+            output.write(buffer, 0, readBytes);
+        input.close();
+        output.close();
+    }
+
+    static public class Compressor extends Dicttool.Command {
+        public static final String COMMAND = "compress";
+        private static final String SUFFIX = ".compressed";
+
+        public Compressor() {
+        }
+
+        public String getHelp() {
+            return "compress <filename>: Compresses a file using gzip compression";
+        }
+
+        public int getArity() {
+            return 1;
+        }
+
+        public void run() throws IOException {
+            final String inFilename = mArgs[0];
+            final String outFilename = inFilename + SUFFIX;
+            final FileInputStream input = new FileInputStream(new File(inFilename));
+            final FileOutputStream output = new FileOutputStream(new File(outFilename));
+            copy(input, new GZIPOutputStream(output));
+        }
+    }
+
+    static public class Uncompressor extends Dicttool.Command {
+        public static final String COMMAND = "uncompress";
+        private static final String SUFFIX = ".uncompressed";
+
+        public Uncompressor() {
+        }
+
+        public String getHelp() {
+            return "uncompress <filename>: Uncompresses a file compressed with gzip compression";
+        }
+
+        public int getArity() {
+            return 1;
+        }
+
+        public void run() throws IOException {
+            final String inFilename = mArgs[0];
+            final String outFilename = inFilename + SUFFIX;
+            final FileInputStream input = new FileInputStream(new File(inFilename));
+            final FileOutputStream output = new FileOutputStream(new File(outFilename));
+            copy(new GZIPInputStream(input), output);
+        }
+    }
+}
diff --git a/tools/dicttool/src/android/inputmethod/latin/dicttool/Dicttool.java b/tools/dicttool/src/android/inputmethod/latin/dicttool/Dicttool.java
new file mode 100644
index 0000000..b78be79
--- /dev/null
+++ b/tools/dicttool/src/android/inputmethod/latin/dicttool/Dicttool.java
@@ -0,0 +1,120 @@
+/**
+ * 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.
+ */
+
+package com.android.inputmethod.latin.dicttool;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class Dicttool {
+
+    public static abstract class Command {
+        protected String[] mArgs;
+        public void setArgs(String[] args) throws IllegalArgumentException {
+            mArgs = args;
+        }
+        abstract public int getArity();
+        abstract public String getHelp();
+        abstract public void run() throws Exception;
+    }
+    static HashMap<String, Class<? extends Command>> sCommands =
+            new HashMap<String, Class<? extends Command>>();
+    static {
+        sCommands.put("info", Info.class);
+        sCommands.put("compress", Compress.Compressor.class);
+        sCommands.put("uncompress", Compress.Uncompressor.class);
+    }
+
+    private static Command getCommandInstance(final String commandName) {
+        try {
+            return sCommands.get(commandName).newInstance();
+        } catch (InstantiationException e) {
+            throw new RuntimeException(commandName + " is not installed");
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(commandName + " is not installed");
+        }
+    }
+
+    private static void help() {
+        System.out.println("Syntax: dicttool <command [arguments]>\nAvailable commands:\n");
+        for (final String commandName : sCommands.keySet()) {
+            System.out.println("*** " + commandName);
+            System.out.println(getCommandInstance(commandName).getHelp());
+            System.out.println("");
+        }
+    }
+
+    private static boolean isCommand(final String commandName) {
+        return sCommands.containsKey(commandName);
+    }
+
+    private String mPreviousCommand = null; // local to the getNextCommand function
+    private Command getNextCommand(final ArrayList<String> arguments) {
+        final String firstArgument = arguments.get(0);
+        final String commandName;
+        if (isCommand(firstArgument)) {
+            commandName = firstArgument;
+            arguments.remove(0);
+        } else if (isCommand(mPreviousCommand)) {
+            commandName = mPreviousCommand;
+        } else {
+            throw new RuntimeException("Unknown command : " + firstArgument);
+        }
+        final Command command = getCommandInstance(commandName);
+        final int arity = command.getArity();
+        if (arguments.size() < arity) {
+            throw new RuntimeException("Not enough arguments to command " + commandName);
+        }
+        final String[] argsArray = new String[arity];
+        arguments.subList(0, arity).toArray(argsArray);
+        for (int i = 0; i < arity; ++i) {
+            // For some reason, ArrayList#removeRange is protected
+            arguments.remove(0);
+        }
+        command.setArgs(argsArray);
+        mPreviousCommand = commandName;
+        return command;
+    }
+
+    private void execute(final ArrayList<String> arguments) {
+        ArrayList<Command> commandsToExecute = new ArrayList<Command>();
+        while (!arguments.isEmpty()) {
+            commandsToExecute.add(getNextCommand(arguments));
+        }
+        for (final Command command : commandsToExecute) {
+            try {
+                command.run();
+            } catch (Exception e) {
+                System.out.println("Exception while processing command "
+                        + command.getClass().getSimpleName() + " : " + e);
+                return;
+            }
+        }
+    }
+
+    public static void main(final String[] args) {
+        if (0 == args.length) {
+            help();
+            return;
+        }
+        if (!isCommand(args[0])) throw new RuntimeException("Unknown command : " + args[0]);
+
+        final ArrayList<String> arguments = new ArrayList<String>(args.length);
+        arguments.addAll(Arrays.asList(args));
+        new Dicttool().execute(arguments);
+    }
+}
diff --git a/tools/dicttool/src/android/inputmethod/latin/dicttool/Info.java b/tools/dicttool/src/android/inputmethod/latin/dicttool/Info.java
new file mode 100644
index 0000000..cb032dd
--- /dev/null
+++ b/tools/dicttool/src/android/inputmethod/latin/dicttool/Info.java
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package com.android.inputmethod.latin.dicttool;
+
+public class Info extends Dicttool.Command {
+    public Info() {
+    }
+
+    public String getHelp() {
+        return "info <filename>: prints various information about a dictionary file";
+    }
+
+    public int getArity() {
+        return 1;
+    }
+
+    public void run() {
+        // TODO: implement this
+        System.out.println("Not implemented yet");
+    }
+}