Merge "Fix the bug that black symbols are shown when only one lanugage is selected. (Update with the files left out from Change-Id: I15f83fc43d91c2c9d74b40fdcecdfe239242d565.)"
diff --git a/java/res/drawable-en-hdpi/sym_keyboard_feedback_delete.png b/java/res/drawable-en-hdpi/sym_keyboard_feedback_delete.png
deleted file mode 100755
index ca76375..0000000
--- a/java/res/drawable-en-hdpi/sym_keyboard_feedback_delete.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_normal_metal.9.png b/java/res/drawable-hdpi/btn_keyboard_normal_metal.9.png
new file mode 100644
index 0000000..b29d6d1
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_normal_metal.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_toggle_off.png b/java/res/drawable-hdpi/btn_keyboard_toggle_off.png
new file mode 100644
index 0000000..bfe7840
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_toggle_off.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_toggle_on.png b/java/res/drawable-hdpi/btn_keyboard_toggle_on.png
new file mode 100644
index 0000000..0a1221e
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_keyboard_toggle_on.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_led_off.9.png b/java/res/drawable-hdpi/btn_led_off.9.png
new file mode 100644
index 0000000..a60f965
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_led_off.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_led_on.9.png b/java/res/drawable-hdpi/btn_led_on.9.png
new file mode 100644
index 0000000..c902609
--- /dev/null
+++ b/java/res/drawable-hdpi/btn_led_on.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/dialog_top_dark_bottom_medium.9.png b/java/res/drawable-hdpi/dialog_top_dark_bottom_medium.9.png
new file mode 100644
index 0000000..ab6c036
--- /dev/null
+++ b/java/res/drawable-hdpi/dialog_top_dark_bottom_medium.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/dialog_top_dark_bottom_medium.png b/java/res/drawable-hdpi/dialog_top_dark_bottom_medium.png
deleted file mode 100755
index 7c79a4f..0000000
--- a/java/res/drawable-hdpi/dialog_top_dark_bottom_medium.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-hdpi/voice_swipe_hint.png b/java/res/drawable-hdpi/voice_swipe_hint.png
new file mode 100644
index 0000000..130f83a
--- /dev/null
+++ b/java/res/drawable-hdpi/voice_swipe_hint.png
Binary files differ
diff --git a/java/res/drawable-land-mdpi/btn_keyboard_key_normal_off.9.png b/java/res/drawable-land-mdpi/btn_keyboard_key_normal_off.9.png
deleted file mode 100644
index bda9b83..0000000
--- a/java/res/drawable-land-mdpi/btn_keyboard_key_normal_off.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-mdpi/btn_keyboard_key_normal_on.9.png b/java/res/drawable-land-mdpi/btn_keyboard_key_normal_on.9.png
deleted file mode 100644
index 0c16ed5..0000000
--- a/java/res/drawable-land-mdpi/btn_keyboard_key_normal_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-mdpi/btn_keyboard_key_pressed_off.9.png b/java/res/drawable-land-mdpi/btn_keyboard_key_pressed_off.9.png
deleted file mode 100644
index bdcf06e..0000000
--- a/java/res/drawable-land-mdpi/btn_keyboard_key_pressed_off.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-land-mdpi/btn_keyboard_key_pressed_on.9.png b/java/res/drawable-land-mdpi/btn_keyboard_key_pressed_on.9.png
deleted file mode 100644
index 79621a9..0000000
--- a/java/res/drawable-land-mdpi/btn_keyboard_key_pressed_on.9.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable/btn_keyboard_normal_metal.9.png b/java/res/drawable-mdpi/btn_keyboard_normal_metal.9.png
similarity index 100%
rename from java/res/drawable/btn_keyboard_normal_metal.9.png
rename to java/res/drawable-mdpi/btn_keyboard_normal_metal.9.png
Binary files differ
diff --git a/java/res/drawable/btn_keyboard_toggle_off.png b/java/res/drawable-mdpi/btn_keyboard_toggle_off.png
similarity index 100%
rename from java/res/drawable/btn_keyboard_toggle_off.png
rename to java/res/drawable-mdpi/btn_keyboard_toggle_off.png
Binary files differ
diff --git a/java/res/drawable/btn_keyboard_toggle_on.png b/java/res/drawable-mdpi/btn_keyboard_toggle_on.png
similarity index 100%
rename from java/res/drawable/btn_keyboard_toggle_on.png
rename to java/res/drawable-mdpi/btn_keyboard_toggle_on.png
Binary files differ
diff --git a/java/res/drawable/btn_led_off.9.png b/java/res/drawable-mdpi/btn_led_off.9.png
similarity index 100%
rename from java/res/drawable/btn_led_off.9.png
rename to java/res/drawable-mdpi/btn_led_off.9.png
Binary files differ
diff --git a/java/res/drawable/btn_led_on.9.png b/java/res/drawable-mdpi/btn_led_on.9.png
similarity index 100%
rename from java/res/drawable/btn_led_on.9.png
rename to java/res/drawable-mdpi/btn_led_on.9.png
Binary files differ
diff --git a/java/res/drawable/cancel.png b/java/res/drawable-mdpi/cancel.png
similarity index 100%
rename from java/res/drawable/cancel.png
rename to java/res/drawable-mdpi/cancel.png
Binary files differ
diff --git a/java/res/drawable/caution.png b/java/res/drawable-mdpi/caution.png
similarity index 100%
rename from java/res/drawable/caution.png
rename to java/res/drawable-mdpi/caution.png
Binary files differ
diff --git a/java/res/drawable/dialog_top_dark_bottom_medium.9.png b/java/res/drawable-mdpi/dialog_top_dark_bottom_medium.9.png
similarity index 100%
rename from java/res/drawable/dialog_top_dark_bottom_medium.9.png
rename to java/res/drawable-mdpi/dialog_top_dark_bottom_medium.9.png
Binary files differ
diff --git a/java/res/drawable/ic_dialog_alert_large.png b/java/res/drawable-mdpi/ic_dialog_alert_large.png
similarity index 100%
rename from java/res/drawable/ic_dialog_alert_large.png
rename to java/res/drawable-mdpi/ic_dialog_alert_large.png
Binary files differ
diff --git a/java/res/drawable/ic_dialog_voice_input.png b/java/res/drawable-mdpi/ic_dialog_voice_input.png
similarity index 100%
rename from java/res/drawable/ic_dialog_voice_input.png
rename to java/res/drawable-mdpi/ic_dialog_voice_input.png
Binary files differ
diff --git a/java/res/drawable/ic_dialog_wave_0_0.png b/java/res/drawable-mdpi/ic_dialog_wave_0_0.png
similarity index 100%
rename from java/res/drawable/ic_dialog_wave_0_0.png
rename to java/res/drawable-mdpi/ic_dialog_wave_0_0.png
Binary files differ
diff --git a/java/res/drawable/ic_dialog_wave_1_3.png b/java/res/drawable-mdpi/ic_dialog_wave_1_3.png
similarity index 100%
rename from java/res/drawable/ic_dialog_wave_1_3.png
rename to java/res/drawable-mdpi/ic_dialog_wave_1_3.png
Binary files differ
diff --git a/java/res/drawable/ic_dialog_wave_2_3.png b/java/res/drawable-mdpi/ic_dialog_wave_2_3.png
similarity index 100%
rename from java/res/drawable/ic_dialog_wave_2_3.png
rename to java/res/drawable-mdpi/ic_dialog_wave_2_3.png
Binary files differ
diff --git a/java/res/drawable/ic_dialog_wave_3_3.png b/java/res/drawable-mdpi/ic_dialog_wave_3_3.png
similarity index 100%
rename from java/res/drawable/ic_dialog_wave_3_3.png
rename to java/res/drawable-mdpi/ic_dialog_wave_3_3.png
Binary files differ
diff --git a/java/res/drawable/ic_dialog_wave_4_3.png b/java/res/drawable-mdpi/ic_dialog_wave_4_3.png
similarity index 100%
rename from java/res/drawable/ic_dialog_wave_4_3.png
rename to java/res/drawable-mdpi/ic_dialog_wave_4_3.png
Binary files differ
diff --git a/java/res/drawable/mic_slash.png b/java/res/drawable-mdpi/mic_slash.png
similarity index 100%
rename from java/res/drawable/mic_slash.png
rename to java/res/drawable-mdpi/mic_slash.png
Binary files differ
diff --git a/java/res/drawable/ok_cancel.png b/java/res/drawable-mdpi/ok_cancel.png
similarity index 100%
rename from java/res/drawable/ok_cancel.png
rename to java/res/drawable-mdpi/ok_cancel.png
Binary files differ
diff --git a/java/res/drawable/speak_now_level0.png b/java/res/drawable-mdpi/speak_now_level0.png
similarity index 100%
rename from java/res/drawable/speak_now_level0.png
rename to java/res/drawable-mdpi/speak_now_level0.png
Binary files differ
diff --git a/java/res/drawable/speak_now_level1.png b/java/res/drawable-mdpi/speak_now_level1.png
similarity index 100%
rename from java/res/drawable/speak_now_level1.png
rename to java/res/drawable-mdpi/speak_now_level1.png
Binary files differ
diff --git a/java/res/drawable/speak_now_level2.png b/java/res/drawable-mdpi/speak_now_level2.png
similarity index 100%
rename from java/res/drawable/speak_now_level2.png
rename to java/res/drawable-mdpi/speak_now_level2.png
Binary files differ
diff --git a/java/res/drawable/speak_now_level3.png b/java/res/drawable-mdpi/speak_now_level3.png
similarity index 100%
rename from java/res/drawable/speak_now_level3.png
rename to java/res/drawable-mdpi/speak_now_level3.png
Binary files differ
diff --git a/java/res/drawable/speak_now_level4.png b/java/res/drawable-mdpi/speak_now_level4.png
similarity index 100%
rename from java/res/drawable/speak_now_level4.png
rename to java/res/drawable-mdpi/speak_now_level4.png
Binary files differ
diff --git a/java/res/drawable/speak_now_level5.png b/java/res/drawable-mdpi/speak_now_level5.png
similarity index 100%
rename from java/res/drawable/speak_now_level5.png
rename to java/res/drawable-mdpi/speak_now_level5.png
Binary files differ
diff --git a/java/res/drawable/speak_now_level6.png b/java/res/drawable-mdpi/speak_now_level6.png
similarity index 100%
rename from java/res/drawable/speak_now_level6.png
rename to java/res/drawable-mdpi/speak_now_level6.png
Binary files differ
diff --git a/java/res/drawable/voice_ime_background.9.png b/java/res/drawable-mdpi/voice_ime_background.9.png
similarity index 100%
rename from java/res/drawable/voice_ime_background.9.png
rename to java/res/drawable-mdpi/voice_ime_background.9.png
Binary files differ
diff --git a/java/res/drawable/voice_swipe_hint.png b/java/res/drawable-mdpi/voice_swipe_hint.png
similarity index 100%
rename from java/res/drawable/voice_swipe_hint.png
rename to java/res/drawable-mdpi/voice_swipe_hint.png
Binary files differ
diff --git a/java/res/drawable/working.png b/java/res/drawable-mdpi/working.png
similarity index 100%
rename from java/res/drawable/working.png
rename to java/res/drawable-mdpi/working.png
Binary files differ
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 4bc1f55..5abbab0 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Velká písmena automaticky"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Zahájit větu velkým písmenem"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Automatická interpunkce"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Rychlé opravy"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Opravuje nejčastější chyby při psaní"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Zobrazit návrhy"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Zobrazovat navržená slova během psaní"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Automatické dokončování"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Stisknutím mezerníku nebo interpunkčního znaménka automaticky vložíte zvýrazněné slovo."</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Návrh Bigram"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Použít předchozí slovo ke zlepšení návrhu"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Žádný"</item>
     <item msgid="1669461741568287396">"Základní"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Chcete-li použít hlasový vstup, stiskněte tlačítko mikrofonu nebo přejeďte prstem přes klávesnici na obrazovce."</string>
     <string name="voice_listening" msgid="467518160751321844">"Mluvte"</string>
     <string name="voice_working" msgid="6666937792815731889">"Probíhá zpracování"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Chyba. Zkuste to prosím znovu."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Připojení se nezdařilo."</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Chyba, řeč je příliš dlouhá."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Jazyk můžete změnit posunutím prstu po mezerníku."</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Uložte slovo opětovným klepnutím"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"K dispozici je slovník"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 750d67b..03a3aaa 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Skriv aut. med stort"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Første bogstav i en sætning skrives med stort"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Foretag automatisk tegnsætning"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Hurtige løsninger"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Retter almindelige stavefejl"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Vis forslag"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Vis ordforslag under indtastning"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Udfyld automatisk"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Mellemrumstast og tegnsætning indsætter automatisk fremhævet ord"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Bigram-forslag"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Brug forrige ord for at forbedre forslag"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Ingen"</item>
     <item msgid="1669461741568287396">"Grundlæggende"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"For at bruge stemme-input skal du trykke på knappen mikrofon eller lade glide fingeren hen over skærmtastaturet."</string>
     <string name="voice_listening" msgid="467518160751321844">"Tal nu"</string>
     <string name="voice_working" msgid="6666937792815731889">"Arbejder"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Fejl. Prøv igen."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke oprette forbindelse"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Fejl. For meget tale."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Træk fingeren på mellemrumstasten for at skifte sprog"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Tast igen for at gemme"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index ed6408d..9e11d54 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Autom. Groß-/Kleinschr."</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Sätze mit Großbuchstaben beginnen"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Autom. Zeichensetzung"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Quick Fixes"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Korrigiert gängige Tippfehler"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Vorschläge anzeigen"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Vorgeschlagene Wörter während des Tippens anzeigen"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Autom. vervollständigen"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Leertaste und Interpunktion fügen autom. ein markiertes Wort ein"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Bigramm-Vorschläge"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Zur Verbesserung des Vorschlags vorheriges Wort verwenden"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Kein"</item>
     <item msgid="1669461741568287396">"Standard"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Um die Spracheingabe zu verwenden, drücken Sie die Mikrofontaste oder ziehen Sie Ihren Finger über die Bildschirmtastatur."</string>
     <string name="voice_listening" msgid="467518160751321844">"Jetzt sprechen"</string>
     <string name="voice_working" msgid="6666937792815731889">"Vorgang läuft"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Fehler. Versuchen Sie es erneut.."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Keine Verbindung"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Fehler – Text zu lang"</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Finger über die Leertaste bewegen, um die Eingabesprache zu wechseln"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Zum Speichern erneut tippen"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfügbar"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index c4a5077..5dea380 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Αυτόματη χρήση κεφαλαίων"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Κεφαλαίο το πρώτο γράμμα της πρότασης"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Αυτόματος τονισμός"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Γρήγορες διορθώσεις"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Διορθώνει συνηθισμένα λάθη πληκτρολόγησης"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Εμφάνιση υποδείξεων"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Προβολή προτεινόμενων λέξεων κατά την πληκτρολόγηση"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Αυτόματη συμπλήρωση"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Τα πλήκ.διαστήμ.και τονισμού εισάγ.αυτόμ.την επιλ.λέξη"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Προτάσεις bigram"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Χρήση προηγούμενης λέξης για τη βελτίωση πρότασης"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Καμία"</item>
     <item msgid="1669461741568287396">"Βασική"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Για να χρησιμοποιήσετε τις φωνητικές εντολές, πιέστε το κουμπί μικροφώνου ή σύρετε το δάχτυλό σας κατά μήκος του πληκτρολογίου της οθόνης."</string>
     <string name="voice_listening" msgid="467518160751321844">"Μιλήστε τώρα"</string>
     <string name="voice_working" msgid="6666937792815731889">"Σε λειτουργία"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Σφάλμα. Δοκιμάστε ξανά."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Δεν ήταν δυνατή η σύνδεση"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Σφάλμα, πολλές λέξεις."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Σύρετε το δάχτυλο στο πλήκτρο διαστήματος για να αλλάξετε γλώσσα"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Πατήστε ξανά για αποθήκευση"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Λεξικό διαθέσιμο"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index cd17dba..f94f7f7 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Poner en mayúscula el inicio de una oración"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Puntuación automática"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Arreglos rápidos"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige errores de escritura comunes"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Mostrar sugerencias"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Mostrar palabras sugeridas mientras escribe"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Completar automát."</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"La barra espaciadora o la puntuación insertan automáticamente la palabra resaltada."</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Sugerencias de Vigoran"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utiliza la palabra anterior para mejorar la sugerencia"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Ninguno"</item>
     <item msgid="1669461741568287396">"Básico"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para realizar entrada por voz, presiona el botón del micrófono o desliza tus dedos por el teclado en pantalla."</string>
     <string name="voice_listening" msgid="467518160751321844">"Habla ahora"</string>
     <string name="voice_working" msgid="6666937792815731889">"Procesando"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Error. Vuelve a intentarlo."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"No se pudo establecer la conexión."</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Error, demasiado discurso."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Deslizarse manualmente por la barra espaciadora para cambiar el idioma"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Presionar nuevamente para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index fbe3ad3..1c8f02b 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Uso de mayúsculas auto."</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Escribir en mayúscula el principio de la frase"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Puntuación automática"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Correcciones rápidas"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige los errores tipográficos que se cometen con más frecuencia."</string>
     <string name="show_suggestions" msgid="507074425254289133">"Mostrar sugerencias"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Muestra las palabras sugeridas mientras se escribe."</string>
     <string name="auto_complete" msgid="1103196318775486023">"Autocompletar"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"La barra espaciadora y los signos de puntuación insertan automáticamente la palabra resaltada."</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Sugerencias de bigramas"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Usar palabra anterior para mejorar sugerencias"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Ninguno"</item>
     <item msgid="1669461741568287396">"Básico"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para utilizar la función de introducción de voz, pulsa el botón de micrófono o desliza el dedo por el teclado en pantalla."</string>
     <string name="voice_listening" msgid="467518160751321844">"Hablar ahora"</string>
     <string name="voice_working" msgid="6666937792815731889">"En curso"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Se ha producido un error. Inténtalo de nuevo."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"No se ha podido establecer conexión."</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Se ha producido un error debido a un exceso de introducción de datos de voz."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Deslizar el dedo por la barra espaciadora para cambiar el idioma"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Volver a tocar para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible."</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 2cabe40..74a0a4e 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Majuscules auto"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Mettre en majuscule la première lettre de chaque phrase"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Ponctuation automatique"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Corrections rapides"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige les fautes de frappe courantes"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Afficher les suggestions"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Afficher les suggestions de terme lors de la saisie"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Saisie semi-automatique"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Insérer auto. le terme surligné avec barre espace/ponctuation"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Suggestions de type bigramme"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Améliorer la suggestion en fonction du mot précédent"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Aucun"</item>
     <item msgid="1669461741568287396">"Simple"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Pour utiliser la saisie vocale, appuyez sur la touche du microphone ou faites glisser votre doigt sur le clavier à l\'écran."</string>
     <string name="voice_listening" msgid="467518160751321844">"Parlez maintenant"</string>
     <string name="voice_working" msgid="6666937792815731889">"Traitement en cours"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Erreur. Veuillez réessayer."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Connexion impossible"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Erreur, discours trop long."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Faites glisser votre doigt sur la barre d\'espacement pour changer la langue."</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Appuyer de nouveau pour enregistrer"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 8100175..52c0b74 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Maiuscole automatiche"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Rendi maiuscole le iniziali delle frasi"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Punteggiatura automat."</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Correzioni veloci"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Corregge gli errori di digitazione più comuni"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Mostra suggerimenti"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Visualizza le parole suggerite durante la digitazione"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Completamento autom."</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Barra spaziatrice e punteggiatura inseriscono la parola evidenziata"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Suggerimenti sui bigrammi"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utilizza parola precedente per migliorare il suggerimento"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Nessuna"</item>
     <item msgid="1669461741568287396">"Base"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Per utilizzare i comandi vocali, premi il pulsante del microfono o fai scorrere il dito sulla tastiera sullo schermo."</string>
     <string name="voice_listening" msgid="467518160751321844">"Parla ora"</string>
     <string name="voice_working" msgid="6666937792815731889">"Elaborazione in corso"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Errore. Riprova più tardi."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Impossibile connettersi."</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Errore: conversazione troppo lunga."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Scorri il dito sulla barra spaziatrice per cambiare la lingua"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Tocca di nuovo per salvare"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 7867684..58a49a2 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"自動大文字変換"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"英字入力で文頭文字を大文字にする"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"句読点を自動入力"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"クイックフィックス"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"よくある誤字・脱字を修正します"</string>
     <string name="show_suggestions" msgid="507074425254289133">"入力候補を表示"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"入力時に入力候補を表示する"</string>
     <string name="auto_complete" msgid="1103196318775486023">"オートコンプリート"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"反転表示されている変換候補をスペースまたは句読点キーで挿入する"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"バイグラム入力候補表示"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"直前の単語から入力候補を予測します"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"なし"</item>
     <item msgid="1669461741568287396">"基本"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"音声入力するには、マイクボタンを押すか画面キーボードをスワイプしてください。"</string>
     <string name="voice_listening" msgid="467518160751321844">"お話しください"</string>
     <string name="voice_working" msgid="6666937792815731889">"処理中"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"エラーです。もう一度お試しください。"</string>
     <string name="voice_network_error" msgid="6649556447401862563">"接続できませんでした"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"音声が長すぎてエラーになりました。"</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"スペースバーで指をスライドさせて言語を変更する"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"←保存するにはもう一度タップ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"辞書を利用できます"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 94d1ff4..804526d 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"자동 대문자화"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"문장의 첫 글자를 대문자로 표시"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"자동 구두점 입력"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"빠른 수정"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"자주 발생하는 오타를 수정합니다."</string>
     <string name="show_suggestions" msgid="507074425254289133">"추천 단어 표시"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"글자를 입력하는 동안 추천 단어를 표시"</string>
     <string name="auto_complete" msgid="1103196318775486023">"자동 완성"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"스페이스바와 문장부호 키로 강조 표시된 단어를 자동 삽입"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Bigram 추천"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"이전 단어를 사용하여 추천 기능 개선"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"없음"</item>
     <item msgid="1669461741568287396">"기본"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"음성 입력을 사용하려면 마이크 버튼을 누르거나 터치 키보드 위로 손가락을 미끄러지듯 움직이세요."</string>
     <string name="voice_listening" msgid="467518160751321844">"지금 말하세요."</string>
     <string name="voice_working" msgid="6666937792815731889">"인식 중"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"오류가 발생했습니다. 다시 시도해 보세요."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"연결할 수 없습니다."</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"음성을 너무 많이 입력했습니다."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"손가락을 스페이스바에서 미끄러지듯 움직여 언어 변경"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← 저장하려면 다시 누르세요."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"사전 사용 가능"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 041d07e..4ff056e 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Stor forbokstav"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Start automatisk setninger med stor bokstav"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Automatisk punktum"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Autokorrektur"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Retter vanlige stavefeil"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Vis forslag"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Vis foreslåtte ord under skriving"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Autofullføring"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Mellomrom og punktum setter automatisk inn valgt ord"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Bigram-forslag"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Bruk forrige ord til å forbedre forslaget"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Ingen"</item>
     <item msgid="1669461741568287396">"Grunnleggende"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Du bruker talekommandoer ved å trykke på mikrofonknappen eller skyve fingeren over tastaturet på skjermen."</string>
     <string name="voice_listening" msgid="467518160751321844">"Snakk nå"</string>
     <string name="voice_working" msgid="6666937792815731889">"Arbeider"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Feil. Prøv på nytt."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke koble til"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Feil – for mye tale"</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Dra fingeren på mellomromstasten for å endre språk"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Trykk på nytt for å lagre"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 00b197b..e65e67c 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Auto-hoofdlettergebruik"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Hoofdletter gebruiken aan het begin van een zin"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Automatische interpunctie"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Snelle oplossingen"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Hiermee worden veelvoorkomende typefouten gecorrigeerd"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Suggesties weergeven"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Voorgestelde woorden weergeven tijdens typen"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Auto-aanvullen"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Gemarkeerd woord automatisch invoegen met spatiebalk en interpunctie"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Digram-suggesties"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Vorig woord gebruiken om suggestie te verbeteren"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Geen"</item>
     <item msgid="1669461741568287396">"Basis"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Als u spraakinvoer gebruikt, drukt u op de microfoonknop of schuift u uw vinger over het schermtoetsenbord."</string>
     <string name="voice_listening" msgid="467518160751321844">"Nu spreken"</string>
     <string name="voice_working" msgid="6666937792815731889">"Wordt uitgevoerd"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Fout. Probeer het opnieuw."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Kan geen verbinding maken"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Fout, te lange spraakinvoer."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Schuif uw vinger over de spatiebalk om de taal te wijzigen"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Tik nogmaals om op te slaan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 0c72727..7026f02 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Wstawiaj wielkie litery"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Zamieniaj na wielką pierwszą literę zdania"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Automatyczna interpunkcja"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Szybkie poprawki"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Poprawia częste błędy wpisywania"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Pokaż sugestie"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Wyświetl sugerowane słowa podczas wpisywania"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Autouzupełnianie"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Spacja i znaki przestankowe wstawiają wyróżnione słowo"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Sugestie dla bigramów"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Używaj poprzedniego wyrazu, aby polepszyć sugestię"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Brak"</item>
     <item msgid="1669461741568287396">"Podstawowy"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Aby skorzystać z wprowadzania głosowego, naciśnij przycisk mikrofonu lub przesuń palcem po klawiaturze ekranowej."</string>
     <string name="voice_listening" msgid="467518160751321844">"Mów teraz"</string>
     <string name="voice_working" msgid="6666937792815731889">"W toku"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Błąd. Spróbuj ponownie."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Nie można nawiązać połączenia"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Błąd, zbyt długa wypowiedź."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Przesuń palcem po spacji, aby zmienić język"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Dotknij ponownie, aby zapisać"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Słownik dostępny"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 35a9cb7..d94d84f 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Letras maiúsculas automáticas"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Colocar inicial maiúscula no início de uma frase"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Pontuação automática"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Correcções rápidas"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige os erros de escrita comuns"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Mostrar sugestões"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Apresentar sugestões de palavras ao escrever"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Conclusão automática"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"A barra de espaços e a pontuação inserem automaticamente uma palavra realçada"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Sugestões Bigram"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Utilizar a palavra anterior para melhorar a sugestão"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Nenhum"</item>
     <item msgid="1669461741568287396">"Básico"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para utilizar a entrada de voz, prima o botão do microfone ou deslize o dedo no teclado do ecrã."</string>
     <string name="voice_listening" msgid="467518160751321844">"Falar agora"</string>
     <string name="voice_working" msgid="6666937792815731889">"A executar"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Não foi possível ligar"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, discurso demasiado longo."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Deslize o dedo pela barra de espaço para alterar o idioma"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Toque novamente para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 235fd65..a20eccc 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Capitaliz. automática"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Colocar em maiúscula o início de uma frase"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Pontuação automática"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Reparos rápidos"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Corrige erros comuns de digitação"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Mostrar sugestões"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Exibir sugestões de palavras durante a digitação"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Conclusão automática"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Barra de espaço e pontuação inserem a palavra destacada"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Sugestões de bigrama"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Usar palavra anterior para melhorar a sugestão"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Nenhum"</item>
     <item msgid="1669461741568287396">"Básico"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Para usar a entrada de voz, pressione o botão com o microfone ou deslize o dedo sobre o teclado na tela."</string>
     <string name="voice_listening" msgid="467518160751321844">"Fale agora"</string>
     <string name="voice_working" msgid="6666937792815731889">"Trabalhando"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Não foi possível conectar"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, fala muito longa."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Deslize o dedo na barra de espaços para alterar o idioma"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Toque novamente para salvar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index e27402c..a1b680e 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Автоподст. заглавных"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Делать заглавной первую букву предложения"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Автопунктуация"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Быстрое исправление"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Исправлять распространенные опечатки"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Предлагать варианты"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Предлагать варианты слов во время ввода"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Автозавершение"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"При нажатии пробела вставлять предложенное слово"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Биграммные подсказки "</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Используйте предыдущее слово, чтобы исправить подсказку"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Нет"</item>
     <item msgid="1669461741568287396">"Основной"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Чтобы использовать голосовой ввод, нажмите кнопку микрофона или проведите пальцем по экранной клавиатуре."</string>
     <string name="voice_listening" msgid="467518160751321844">"Говорите"</string>
     <string name="voice_working" msgid="6666937792815731889">"Выполняется обработка"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Ошибка. Повторите попытку."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Ошибка подключения"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Слишком длинная фраза"</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Для изменения языка проведите пальцем по пробелу"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Нажмите повторно, чтобы сохранить"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Доступен словарь"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 9c6c221..82f6529 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Automatiska versaler"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Använd versal i början av mening"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Automatiska punkter"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Snabba lösningar"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Åtgärdar automatiskt vanliga misstag"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Visa förslag"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Visar ordförslag när du skriver"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Komplettera automatiskt"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Blanksteg och punkt infogar automatiskt markerat ord"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Bigramförslag"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Förbättra förslaget med föregående ord"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Inget"</item>
     <item msgid="1669461741568287396">"Grundinställningar"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Om du vill använda röstinmatning trycker du på mikrofonknappen eller drar fingret över tangentbordet på skärmen."</string>
     <string name="voice_listening" msgid="467518160751321844">"Tala nu"</string>
     <string name="voice_working" msgid="6666937792815731889">"Fungerar"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Fel. Försök igen."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Det gick inte att ansluta"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Fel, för mycket tal."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Dra med fingret på blanksteg om du vill ändra språk"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Peka igen för att spara"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"En ordlista är tillgänglig"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 0fbdc7d..820327b 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak büyük harf yap"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"Cümlenin baş harfini büyük yap"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"Otomatik noktalama"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"Hızlı onarımlar"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"Yaygın olarak yapılan yazım hatalarını düzeltir"</string>
     <string name="show_suggestions" msgid="507074425254289133">"Önerileri göster"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"Yazarken önerilen kelimeleri görüntüle"</string>
     <string name="auto_complete" msgid="1103196318775486023">"Otomatik tamamla"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"Boşluk tuşu ve noktalama vurgulanan kelimeyi otomatik ekler"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"Bigram Önerileri"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Öneriyi geliştirmek için önceki kelimeyi kullanın"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"Yok"</item>
     <item msgid="1669461741568287396">"Temel"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"Ses girişini kullanmak için mikrofon düğmesine basın veya parmağınızı dokunmatik klavye üzerinde kaydırın."</string>
     <string name="voice_listening" msgid="467518160751321844">"Şimdi konuşun"</string>
     <string name="voice_working" msgid="6666937792815731889">"Çalışıyor"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"Hata. Lütfen tekrar deneyin."</string>
     <string name="voice_network_error" msgid="6649556447401862563">"Bağlanamadı"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"Hata, çok uzun konuşma."</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"Dili değiştirmek için parmağınızı boşluk çubuğu üzerinde kaydırın"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← Kaydetmek için tekrar dokunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sözlük kullanılabilir"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 9c9b257..953c93b 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"自动大写"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"句首字母大写"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"自动加标点"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"快速纠正"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"纠正常见的输入错误"</string>
     <string name="show_suggestions" msgid="507074425254289133">"显示建议"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"输入时启用联想提示"</string>
     <string name="auto_complete" msgid="1103196318775486023">"自动填写"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"按空格键和标点符号时自动插入突出显示的字词"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"双连词建议"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"使用以前的字词改进建议"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"无"</item>
     <item msgid="1669461741568287396">"基本模式"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"要使用语音输入,请按麦克风按钮或者在屏幕键盘上滑动手指。"</string>
     <string name="voice_listening" msgid="467518160751321844">"请开始说话"</string>
     <string name="voice_working" msgid="6666937792815731889">"正在处理"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"出错,请重试。"</string>
     <string name="voice_network_error" msgid="6649556447401862563">"无法连接"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"出错,语音过长。"</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"在空格键上滑动手指可更改语言"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← 再次点按即可保存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"提供字典"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 4f83be4..7748589 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -39,14 +39,15 @@
     <string name="auto_cap" msgid="1719746674854628252">"自動大寫"</string>
     <string name="auto_cap_summary" msgid="3260681697600786825">"句首字母大寫"</string>
     <string name="auto_punctuate" msgid="7276672334264521751">"自動標點"</string>
-    <!-- no translation found for auto_punctuate_summary (6589441565817502132) -->
-    <skip />
+    <string name="auto_punctuate_summary" msgid="6589441565817502132"></string>
     <string name="quick_fixes" msgid="5353213327680897927">"快速修正"</string>
     <string name="quick_fixes_summary" msgid="3405028402510332373">"修正一般打字錯誤"</string>
     <string name="show_suggestions" msgid="507074425254289133">"顯示建議"</string>
     <string name="show_suggestions_summary" msgid="1989672863935759654">"打字時顯示建議字詞"</string>
     <string name="auto_complete" msgid="1103196318775486023">"自動完成"</string>
     <string name="auto_complete_summary" msgid="6113149638718274624">"在反白顯示的字詞處自動插入空白鍵和標點符號鍵盤"</string>
+    <string name="bigram_suggestion" msgid="1323347224043514969">"雙連詞建議"</string>
+    <string name="bigram_suggestion_summary" msgid="4383845146070101531">"使用前一個字詞來改善建議"</string>
   <string-array name="prediction_modes">
     <item msgid="4870266572388153286">"無"</item>
     <item msgid="1669461741568287396">"基本模式"</item>
@@ -89,8 +90,7 @@
     <string name="voice_hint_dialog_message" msgid="6892342981545727994">"如要使用語音輸入,按下 [麥克風] 按鈕,或將手指滑過螢幕小鍵盤即可。"</string>
     <string name="voice_listening" msgid="467518160751321844">"請說話"</string>
     <string name="voice_working" msgid="6666937792815731889">"辨識中"</string>
-    <!-- no translation found for voice_initializing (661962047129906646) -->
-    <skip />
+    <string name="voice_initializing" msgid="661962047129906646"></string>
     <string name="voice_error" msgid="5140896300312186162">"發生錯誤,請再試一次。"</string>
     <string name="voice_network_error" msgid="6649556447401862563">"無法連線"</string>
     <string name="voice_too_much_speech" msgid="5746973620134227376">"錯誤:語音內容過長。"</string>
@@ -130,4 +130,12 @@
     <string name="language_selection_summary" msgid="187110938289512256">"以手指在空白鍵上滑動可變更語言"</string>
     <string name="hint_add_to_dictionary" msgid="8058519710062071085">"← 再次輕按可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string>
+    <!-- no translation found for prefs_enable_log (6620424505072963557) -->
+    <skip />
+    <!-- no translation found for prefs_description_log (5827825607258246003) -->
+    <skip />
+    <!-- no translation found for keyboard_layout (437433231038683666) -->
+    <skip />
+    <!-- no translation found for prefs_debug_mode (3889340783846594980) -->
+    <skip />
 </resources>
diff --git a/java/src/com/android/inputmethod/latin/AutoDictionary.java b/java/src/com/android/inputmethod/latin/AutoDictionary.java
index 94331d3..4fbb5b0 100644
--- a/java/src/com/android/inputmethod/latin/AutoDictionary.java
+++ b/java/src/com/android/inputmethod/latin/AutoDictionary.java
@@ -83,14 +83,14 @@
         sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE);
     }
 
-    private static DatabaseHelper mOpenHelper = null;
+    private static DatabaseHelper sOpenHelper = null;
 
     public AutoDictionary(Context context, LatinIME ime, String locale, int dicTypeId) {
         super(context, dicTypeId);
         mIme = ime;
         mLocale = locale;
-        if (mOpenHelper == null) {
-            mOpenHelper = new DatabaseHelper(getContext());
+        if (sOpenHelper == null) {
+            sOpenHelper = new DatabaseHelper(getContext());
         }
         if (mLocale != null && mLocale.length() > 1) {
             loadDictionary();
@@ -169,7 +169,7 @@
             // Nothing pending? Return
             if (mPendingWrites.isEmpty()) return;
             // Create a background thread to write the pending entries
-            new UpdateDbTask(getContext(), mOpenHelper, mPendingWrites, mLocale).execute();
+            new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute();
             // Create a new map for writing new entries into while the old one is written to db
             mPendingWrites = new HashMap<String, Integer>();
         }
@@ -209,7 +209,7 @@
         qb.setProjectionMap(sDictProjectionMap);
 
         // Get the database and run the query
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        SQLiteDatabase db = sOpenHelper.getReadableDatabase();
         Cursor c = qb.query(db, null, selection, selectionArgs, null, null,
                 DEFAULT_SORT_ORDER);
         return c;
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index e2c0c4c..69c2b94 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -42,8 +42,8 @@
 
     private static final String TAG = "BinaryDictionary";
     private static final int MAX_ALTERNATIVES = 16;
-    private static final int MAX_WORDS = 16;
-    private static final int MAX_BIGRAMS = 255; // TODO Probably don't need all 255
+    private static final int MAX_WORDS = 18;
+    private static final int MAX_BIGRAMS = 60;
 
     private static final int TYPED_LETTER_MULTIPLIER = 2;
     private static final boolean ENABLE_MISSED_CHARACTERS = true;
@@ -140,8 +140,10 @@
             Log.w(TAG, "No available memory for binary dictionary");
         } finally {
             try {
-                for (int i = 0;i < is.length; i++) {
-                    is[i].close();
+                if (is != null) {
+                    for (int i = 0; i < is.length; i++) {
+                        is[i].close();
+                    }
                 }
             } catch (IOException e) {
                 Log.w(TAG, "Failed to close input stream");
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index faf72c9..7fcc3d5 100755
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -341,6 +341,12 @@
         mShowingAddToDictionary = true;
     }
 
+    public boolean dismissAddToDictionaryHint() {
+        if (!mShowingAddToDictionary) return false;
+        clear();
+        return true;
+    }
+
     public void scrollPrev() {
         int i = 0;
         final int count = Math.min(mSuggestions.size(), MAX_SUGGESTIONS);
diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
index 7567828..ab75868 100644
--- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
@@ -125,8 +125,8 @@
                                 super.addWord(word, FREQUENCY_FOR_CONTACTS);
                                 if (!TextUtils.isEmpty(prevWord)) {
                                     // TODO Do not add email address
-                                    super.addBigrams(prevWord, word,
-                                            FREQUENCY_FOR_CONTACTS_BIGRAM);
+                                    // Not so critical
+                                    super.setBigram(prevWord, word, FREQUENCY_FOR_CONTACTS_BIGRAM);
                                 }
                                 prevWord = word;
                             }
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index 53f9ed8..e954c08 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -20,8 +20,6 @@
 
 import android.content.Context;
 import android.os.AsyncTask;
-import android.os.SystemClock;
-import android.util.Log;
 
 /**
  * Base class for an in-memory dictionary that can grow dynamically and can
@@ -325,12 +323,21 @@
         }
     }
 
+    protected int setBigram(String word1, String word2, int frequency) {
+        return addOrSetBigram(word1, word2, frequency, false);
+    }
+
+    protected int addBigram(String word1, String word2, int frequency) {
+        return addOrSetBigram(word1, word2, frequency, true);
+    }
+
     /**
      * Adds bigrams to the in-memory trie structure that is being used to retrieve any word
-     * @param addFrequency adding frequency of the pair
+     * @param frequency frequency for this bigrams
+     * @param addFrequency if true, it adds to current frequency
      * @return returns the final frequency
      */
-    protected int addBigrams(String word1, String word2, int addFrequency) {
+    private int addOrSetBigram(String word1, String word2, int frequency, boolean addFrequency) {
         Node firstWord = searchWord(mRoots, word1, 0, null);
         Node secondWord = searchWord(mRoots, word2, 0, null);
         LinkedList<NextWord> bigram = firstWord.ngrams;
@@ -340,14 +347,18 @@
         } else {
             for (NextWord nw : bigram) {
                 if (nw.word == secondWord) {
-                    nw.frequency += addFrequency;
+                    if (addFrequency) {
+                        nw.frequency += frequency;
+                    } else {
+                        nw.frequency = frequency;
+                    }
                     return nw.frequency;
                 }
             }
         }
-        NextWord nw = new NextWord(secondWord, addFrequency);
+        NextWord nw = new NextWord(secondWord, frequency);
         firstWord.ngrams.add(nw);
-        return addFrequency;
+        return frequency;
     }
 
     /**
@@ -385,22 +396,44 @@
         return searchWord(childNode.children, word, depth + 1, childNode);
     }
 
-    @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback, int[] nextLettersFrequencies) {
+    // @VisibleForTesting
+    boolean reloadDictionaryIfRequired() {
         synchronized (mUpdatingLock) {
             // If we need to update, start off a background task
             if (mRequiresReload) startDictionaryLoadingTaskLocked();
             // Currently updating contacts, don't return any results.
-            if (mUpdatingDictionary) return;
+            return mUpdatingDictionary;
         }
+    }
 
+    private void runReverseLookUp(final CharSequence previousWord, final WordCallback callback) {
         Node prevWord = searchNode(mRoots, previousWord, 0, previousWord.length());
         if (prevWord != null && prevWord.ngrams != null) {
             reverseLookUp(prevWord.ngrams, callback);
         }
     }
 
+    @Override
+    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
+            final WordCallback callback, int[] nextLettersFrequencies) {
+        if (!reloadDictionaryIfRequired()) {
+            runReverseLookUp(previousWord, callback);
+        }
+    }
+
+    /**
+     * Used only for testing purposes
+     * This function will wait for loading from database to be done
+     */
+    void waitForDictionaryLoading() {
+        while (mUpdatingDictionary) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
     /**
      * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words
      * through callback.
@@ -413,15 +446,18 @@
         for (NextWord nextWord : terminalNodes) {
             node = nextWord.word;
             freq = nextWord.frequency;
-            sb.setLength(0);
-            do {
-                sb.insert(0, node.code);
-                node = node.parent;
-            } while(node != null);
+            // TODO Not the best way to limit suggestion threshold
+            if (freq >= UserBigramDictionary.SUGGEST_THRESHOLD) {
+                sb.setLength(0);
+                do {
+                    sb.insert(0, node.code);
+                    node = node.parent;
+                } while(node != null);
 
-            // TODO better way to feed char array?
-            callback.addWord(sb.toString().toCharArray(), 0, sb.length(), freq, mDicTypeId,
-                    DataType.BIGRAM);
+                // TODO better way to feed char array?
+                callback.addWord(sb.toString().toCharArray(), 0, sb.length(), freq, mDicTypeId,
+                        DataType.BIGRAM);
+            }
         }
     }
 
@@ -460,18 +496,11 @@
         @Override
         protected Void doInBackground(Void... v) {
             loadDictionaryAsync();
-            return null;
-        }
-
-        @Override
-        protected void onPostExecute(Void result) {
-            // TODO Auto-generated method stub
             synchronized (mUpdatingLock) {
                 mUpdatingDictionary = false;
             }
-            super.onPostExecute(result);
+            return null;
         }
-        
     }
 
     static char toLowerCase(char c) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index bbca316..3ee9fe8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -163,8 +163,7 @@
     KeyboardSwitcher mKeyboardSwitcher;
 
     private UserDictionary mUserDictionary;
-    // User Bigram is disabled for now
-    //private UserBigramDictionary mUserBigramDictionary;
+    private UserBigramDictionary mUserBigramDictionary;
     private ContactsDictionary mContactsDictionary;
     private AutoDictionary mAutoDictionary;
 
@@ -454,15 +453,12 @@
             mAutoDictionary.close();
         }
         mAutoDictionary = new AutoDictionary(this, this, mInputLocale, Suggest.DIC_AUTO);
-        // User Bigram is disabled for now
-        /*
         if (mUserBigramDictionary != null) {
             mUserBigramDictionary.close();
         }
         mUserBigramDictionary = new UserBigramDictionary(this, this, mInputLocale,
-                Suggest.DIC_USERBIGRAM);
+                Suggest.DIC_USER);
         mSuggest.setUserBigramDictionary(mUserBigramDictionary);
-        */
         mSuggest.setUserDictionary(mUserDictionary);
         mSuggest.setContactsDictionary(mContactsDictionary);
         mSuggest.setAutoDictionary(mAutoDictionary);
@@ -698,8 +694,7 @@
             mKeyboardSwitcher.getInputView().closing();
         }
         if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites();
-        // User Bigram is disabled for now
-        //if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites();
+        if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites();
     }
 
     @Override
@@ -1060,6 +1055,9 @@
 
     public boolean addWordToDictionary(String word) {
         mUserDictionary.addWord(word, 128);
+        // Suggestion strip should be updated after the operation of adding word to the
+        // user dictionary
+        postUpdateSuggestions();
         return true;
     }
 
@@ -1211,9 +1209,20 @@
         } else if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
             ic.deleteSurroundingText(mEnteredText.length(), 0);
         } else if (deleteChar) {
-            sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
-            if (mDeleteCount > DELETE_ACCELERATE_AT) {
+            if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) {
+                // Go back to the suggestion mode if the user canceled the
+                // "Tap again to save".
+                // NOTE: In gerenal, we don't revert the word when backspacing
+                // from a manual suggestion pick.  We deliberately chose a
+                // different behavior only in the case of picking the first
+                // suggestion (typed word).  It's intentional to have made this
+                // inconsistent with backspacing after selecting other suggestions.
+                revertLastWord(deleteChar);
+            } else {
                 sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+                if (mDeleteCount > DELETE_ACCELERATE_AT) {
+                    sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+                }
             }
         }
         mJustRevertedSeparator = null;
@@ -1305,6 +1314,11 @@
             mVoiceInput.incrementTextModificationInsertPunctuationCount(1);
         }
 
+        // Should dismiss the "Tap again to save" message when handling separator
+        if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) {
+            postUpdateSuggestions();
+        }
+
         boolean pickedDefault = false;
         // Handle separator
         InputConnection ic = getCurrentInputConnection();
@@ -1375,6 +1389,11 @@
             mWord.reset();
             return;
         }
+        // Skip if result is null. It happens in some edge case.
+        if (TextUtils.isEmpty(result)) {
+            return;
+        }
+
         // Make a copy of the CharSequence, since it is/could be a mutable CharSequence
         final String resultCopy = result.toString();
         TypedWordAlternatives entry = new TypedWordAlternatives(resultCopy,
@@ -1983,15 +2002,14 @@
                     && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) {
                 mAutoDictionary.addWord(suggestion.toString(), frequencyDelta);
             }
-            // User Bigram is disabled for now
-            /*
+
             if (mUserBigramDictionary != null) {
-                CharSequence prevWord = EditingUtil.getPreviousWord(getCurrentInputConnection());
+                CharSequence prevWord = EditingUtil.getPreviousWord(getCurrentInputConnection(),
+                        mSentenceSeparators);
                 if (!TextUtils.isEmpty(prevWord)) {
-                    mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString(), 1);
+                    mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString());
                 }
             }
-            */
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index cfb6910..a96737f 100755
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -78,12 +78,13 @@
     private Dictionary mUserBigramDictionary;
 
     private int mPrefMaxSuggestions = 12;
-    private int mPrefMaxBigrams = 255;
+
+    private static final int PREF_MAX_BIGRAMS = 60;
 
     private boolean mAutoTextEnabled;
 
     private int[] mPriorities = new int[mPrefMaxSuggestions];
-    private int[] mBigramPriorities = new int[mPrefMaxBigrams];
+    private int[] mBigramPriorities = new int[PREF_MAX_BIGRAMS];
 
     // Handle predictive correction for only the first 1280 characters for performance reasons
     // If we support scripts that need latin characters beyond that, we should probably use some
@@ -92,7 +93,7 @@
     // latin characters.
     private int[] mNextLettersFrequencies = new int[1280];
     private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>();
-    private ArrayList<CharSequence> mBigramSuggestions  = new ArrayList<CharSequence>();
+    ArrayList<CharSequence> mBigramSuggestions  = new ArrayList<CharSequence>();
     private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>();
     private boolean mHaveCorrection;
     private CharSequence mOriginalWord;
@@ -173,7 +174,7 @@
         }
         mPrefMaxSuggestions = maxSuggestions;
         mPriorities = new int[mPrefMaxSuggestions];
-        mBigramPriorities = new int[mPrefMaxBigrams];
+        mBigramPriorities = new int[PREF_MAX_BIGRAMS];
         collectGarbage(mSuggestions, mPrefMaxSuggestions);
         while (mStringPool.size() < mPrefMaxSuggestions) {
             StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
@@ -242,7 +243,7 @@
                 || mCorrectionMode == CORRECTION_BASIC)) {
             // At first character typed, search only the bigrams
             Arrays.fill(mBigramPriorities, 0);
-            collectGarbage(mBigramSuggestions, mPrefMaxBigrams);
+            collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS);
 
             if (!TextUtils.isEmpty(prevWordForBigram)) {
                 CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase();
@@ -401,7 +402,7 @@
         if(dataType == Dictionary.DataType.BIGRAM) {
             suggestions = mBigramSuggestions;
             priorities = mBigramPriorities;
-            prefMaxSuggestions = mPrefMaxBigrams;
+            prefMaxSuggestions = PREF_MAX_BIGRAMS;
         } else {
             suggestions = mSuggestions;
             priorities = mPriorities;
@@ -443,7 +444,6 @@
                 pos++;
             }
         }
-
         if (pos >= prefMaxSuggestions) {
             return true;
         }
diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
new file mode 100644
index 0000000..c3eab94
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2010 Google Inc.
+ *
+ * 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 java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.os.AsyncTask;
+import android.provider.BaseColumns;
+import android.util.Log;
+
+/**
+ * Stores all the pairs user types in databases. Prune the database if the size
+ * gets too big. Unlike AutoDictionary, it even stores the pairs that are already
+ * in the dictionary.
+ */
+public class UserBigramDictionary extends ExpandableDictionary {
+    private static final String TAG = "UserBigramDictionary";
+
+    /** Any pair being typed or picked */
+    private static final int FREQUENCY_FOR_TYPED = 2;
+
+    /** Maximum frequency for all pairs */
+    private static final int FREQUENCY_MAX = 127;
+
+    /**
+     * If this pair is typed 6 times, it would be suggested.
+     * Should be smaller than ContactsDictionary.FREQUENCY_FOR_CONTACTS_BIGRAM
+     */
+    protected static final int SUGGEST_THRESHOLD = 6 * FREQUENCY_FOR_TYPED;
+
+    /** Maximum number of pairs. Pruning will start when databases goes above this number. */
+    private static int sMaxUserBigrams = 10000;
+
+    /**
+     * When it hits maximum bigram pair, it will delete until you are left with
+     * only (sMaxUserBigrams - sDeleteUserBigrams) pairs.
+     * Do not keep this number small to avoid deleting too often.
+     */
+    private static int sDeleteUserBigrams = 1000;
+
+    /**
+     * Database version should increase if the database structure changes
+     */
+    private static final int DATABASE_VERSION = 1;
+
+    private static final String DATABASE_NAME = "userbigram_dict.db";
+
+    /** Name of the words table in the database */
+    private static final String MAIN_TABLE_NAME = "main";
+    // TODO: Consume less space by using a unique id for locale instead of the whole
+    // 2-5 character string. (Same TODO from AutoDictionary)
+    private static final String MAIN_COLUMN_ID = BaseColumns._ID;
+    private static final String MAIN_COLUMN_WORD1 = "word1";
+    private static final String MAIN_COLUMN_WORD2 = "word2";
+    private static final String MAIN_COLUMN_LOCALE = "locale";
+
+    /** Name of the frequency table in the database */
+    private static final String FREQ_TABLE_NAME = "frequency";
+    private static final String FREQ_COLUMN_ID = BaseColumns._ID;
+    private static final String FREQ_COLUMN_PAIR_ID = "pair_id";
+    private static final String FREQ_COLUMN_FREQUENCY = "freq";
+
+    private final LatinIME mIme;
+
+    /** Locale for which this auto dictionary is storing words */
+    private String mLocale;
+
+    private HashSet<Bigram> mPendingWrites = new HashSet<Bigram>();
+    private final Object mPendingWritesLock = new Object();
+    private static volatile boolean sUpdatingDB = false;
+
+    private final static HashMap<String, String> sDictProjectionMap;
+
+    static {
+        sDictProjectionMap = new HashMap<String, String>();
+        sDictProjectionMap.put(MAIN_COLUMN_ID, MAIN_COLUMN_ID);
+        sDictProjectionMap.put(MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD1);
+        sDictProjectionMap.put(MAIN_COLUMN_WORD2, MAIN_COLUMN_WORD2);
+        sDictProjectionMap.put(MAIN_COLUMN_LOCALE, MAIN_COLUMN_LOCALE);
+
+        sDictProjectionMap.put(FREQ_COLUMN_ID, FREQ_COLUMN_ID);
+        sDictProjectionMap.put(FREQ_COLUMN_PAIR_ID, FREQ_COLUMN_PAIR_ID);
+        sDictProjectionMap.put(FREQ_COLUMN_FREQUENCY, FREQ_COLUMN_FREQUENCY);
+    }
+
+    private static DatabaseHelper sOpenHelper = null;
+
+    private static class Bigram {
+        String word1;
+        String word2;
+        int frequency;
+
+        Bigram(String word1, String word2, int frequency) {
+            this.word1 = word1;
+            this.word2 = word2;
+            this.frequency = frequency;
+        }
+
+        @Override
+        public boolean equals(Object bigram) {
+            Bigram bigram2 = (Bigram) bigram;
+            return (word1.equals(bigram2.word1) && word2.equals(bigram2.word2));
+        }
+
+        @Override
+        public int hashCode() {
+            return (word1 + " " + word2).hashCode();
+        }
+    }
+
+    public void setDatabaseMax(int maxUserBigram) {
+        sMaxUserBigrams = maxUserBigram;
+    }
+
+    public void setDatabaseDelete(int deleteUserBigram) {
+        sDeleteUserBigrams = deleteUserBigram;
+    }
+
+    public UserBigramDictionary(Context context, LatinIME ime, String locale, int dicTypeId) {
+        super(context, dicTypeId);
+        mIme = ime;
+        mLocale = locale;
+        if (sOpenHelper == null) {
+            sOpenHelper = new DatabaseHelper(getContext());
+        }
+        if (mLocale != null && mLocale.length() > 1) {
+            loadDictionary();
+        }
+    }
+
+    @Override
+    public void close() {
+        flushPendingWrites();
+        // Don't close the database as locale changes will require it to be reopened anyway
+        // Also, the database is written to somewhat frequently, so it needs to be kept alive
+        // throughout the life of the process.
+        // mOpenHelper.close();
+        super.close();
+    }
+
+    /**
+     * Pair will be added to the userbigram database.
+     */
+    public int addBigrams(String word1, String word2) {
+        // remove caps
+        if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) {
+            word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1);
+        }
+
+        int freq = super.addBigram(word1, word2, FREQUENCY_FOR_TYPED);
+        if (freq > FREQUENCY_MAX) freq = FREQUENCY_MAX;
+        synchronized (mPendingWritesLock) {
+            if (freq == FREQUENCY_FOR_TYPED || mPendingWrites.isEmpty()) {
+                mPendingWrites.add(new Bigram(word1, word2, freq));
+            } else {
+                Bigram bi = new Bigram(word1, word2, freq);
+                mPendingWrites.remove(bi);
+                mPendingWrites.add(bi);
+            }
+        }
+
+        return freq;
+    }
+
+    /**
+     * Schedules a background thread to write any pending words to the database.
+     */
+    public void flushPendingWrites() {
+        synchronized (mPendingWritesLock) {
+            // Nothing pending? Return
+            if (mPendingWrites.isEmpty()) return;
+            // Create a background thread to write the pending entries
+            new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute();
+            // Create a new map for writing new entries into while the old one is written to db
+            mPendingWrites = new HashSet<Bigram>();
+        }
+    }
+
+    /** Used for testing purpose **/
+    void waitUntilUpdateDBDone() {
+        synchronized (mPendingWritesLock) {
+            while (sUpdatingDB) {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                }
+            }
+            return;
+        }
+    }
+
+    @Override
+    public void loadDictionaryAsync() {
+        // Load the words that correspond to the current input locale
+        Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale });
+        try {
+            if (cursor.moveToFirst()) {
+                int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1);
+                int word2Index = cursor.getColumnIndex(MAIN_COLUMN_WORD2);
+                int frequencyIndex = cursor.getColumnIndex(FREQ_COLUMN_FREQUENCY);
+                while (!cursor.isAfterLast()) {
+                    String word1 = cursor.getString(word1Index);
+                    String word2 = cursor.getString(word2Index);
+                    int frequency = cursor.getInt(frequencyIndex);
+                    // Safeguard against adding really long words. Stack may overflow due
+                    // to recursive lookup
+                    if (word1.length() < MAX_WORD_LENGTH && word2.length() < MAX_WORD_LENGTH) {
+                        super.setBigram(word1, word2, frequency);
+                    }
+                    cursor.moveToNext();
+                }
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Query the database
+     */
+    private Cursor query(String selection, String[] selectionArgs) {
+        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+        // main INNER JOIN frequency ON (main._id=freq.pair_id)
+        qb.setTables(MAIN_TABLE_NAME + " INNER JOIN " + FREQ_TABLE_NAME + " ON ("
+                + MAIN_TABLE_NAME + "." + MAIN_COLUMN_ID + "=" + FREQ_TABLE_NAME + "."
+                + FREQ_COLUMN_PAIR_ID +")");
+
+        qb.setProjectionMap(sDictProjectionMap);
+
+        // Get the database and run the query
+        SQLiteDatabase db = sOpenHelper.getReadableDatabase();
+        Cursor c = qb.query(db,
+                new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY },
+                selection, selectionArgs, null, null, null);
+        return c;
+    }
+
+    /**
+     * This class helps open, create, and upgrade the database file.
+     */
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            db.execSQL("PRAGMA foreign_keys = ON;");
+            db.execSQL("CREATE TABLE " + MAIN_TABLE_NAME + " ("
+                    + MAIN_COLUMN_ID + " INTEGER PRIMARY KEY,"
+                    + MAIN_COLUMN_WORD1 + " TEXT,"
+                    + MAIN_COLUMN_WORD2 + " TEXT,"
+                    + MAIN_COLUMN_LOCALE + " TEXT"
+                    + ");");
+            db.execSQL("CREATE TABLE " + FREQ_TABLE_NAME + " ("
+                    + FREQ_COLUMN_ID + " INTEGER PRIMARY KEY,"
+                    + FREQ_COLUMN_PAIR_ID + " INTEGER,"
+                    + FREQ_COLUMN_FREQUENCY + " INTEGER,"
+                    + "FOREIGN KEY(" + FREQ_COLUMN_PAIR_ID + ") REFERENCES " + MAIN_TABLE_NAME
+                    + "(" + MAIN_COLUMN_ID + ")" + " ON DELETE CASCADE"
+                    + ");");
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+                    + newVersion + ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS " + MAIN_TABLE_NAME);
+            db.execSQL("DROP TABLE IF EXISTS " + FREQ_TABLE_NAME);
+            onCreate(db);
+        }
+    }
+
+    /**
+     * Async task to write pending words to the database so that it stays in sync with
+     * the in-memory trie.
+     */
+    private static class UpdateDbTask extends AsyncTask<Void, Void, Void> {
+        private final HashSet<Bigram> mMap;
+        private final DatabaseHelper mDbHelper;
+        private final String mLocale;
+
+        public UpdateDbTask(Context context, DatabaseHelper openHelper,
+                HashSet<Bigram> pendingWrites, String locale) {
+            mMap = pendingWrites;
+            mLocale = locale;
+            mDbHelper = openHelper;
+        }
+
+        /** Prune any old data if the database is getting too big. */
+        private void checkPruneData(SQLiteDatabase db) {
+            db.execSQL("PRAGMA foreign_keys = ON;");
+            Cursor c = db.query(FREQ_TABLE_NAME, new String[] { FREQ_COLUMN_PAIR_ID },
+                    null, null, null, null, null);
+            try {
+                int totalRowCount = c.getCount();
+                // prune out old data if we have too much data
+                if (totalRowCount > sMaxUserBigrams) {
+                    int numDeleteRows = (totalRowCount - sMaxUserBigrams) + sDeleteUserBigrams;
+                    int pairIdColumnId = c.getColumnIndex(FREQ_COLUMN_PAIR_ID);
+                    c.moveToFirst();
+                    int count = 0;
+                    while (count < numDeleteRows && !c.isAfterLast()) {
+                        String pairId = c.getString(pairIdColumnId);
+                        // Deleting from MAIN table will delete the frequencies
+                        // due to FOREIGN KEY .. ON DELETE CASCADE
+                        db.delete(MAIN_TABLE_NAME, MAIN_COLUMN_ID + "=?",
+                            new String[] { pairId });
+                        c.moveToNext();
+                        count++;
+                    }
+                }
+            } finally {
+                c.close();
+            }
+        }
+
+        @Override
+        protected void onPreExecute() {
+            sUpdatingDB = true;
+        }
+
+        @Override
+        protected Void doInBackground(Void... v) {
+            SQLiteDatabase db = mDbHelper.getWritableDatabase();
+            db.execSQL("PRAGMA foreign_keys = ON;");
+            // Write all the entries to the db
+            Iterator<Bigram> iterator = mMap.iterator();
+            while (iterator.hasNext()) {
+                Bigram bi = iterator.next();
+
+                // find pair id
+                Cursor c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID },
+                        MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND "
+                        + MAIN_COLUMN_LOCALE + "=?",
+                        new String[] { bi.word1, bi.word2, mLocale }, null, null, null);
+
+                int pairId;
+                if (c.moveToFirst()) {
+                    // existing pair
+                    pairId = c.getInt(c.getColumnIndex(MAIN_COLUMN_ID));
+                    db.delete(FREQ_TABLE_NAME, FREQ_COLUMN_PAIR_ID + "=?",
+                            new String[] { Integer.toString(pairId) });
+                } else {
+                    // new pair
+                    Long pairIdLong = db.insert(MAIN_TABLE_NAME, null,
+                            getContentValues(bi.word1, bi.word2, mLocale));
+                    pairId = pairIdLong.intValue();
+                }
+                c.close();
+
+                // insert new frequency
+                long s = db.insert(FREQ_TABLE_NAME, null,
+                        getFrequencyContentValues(pairId, bi.frequency));
+            }
+            checkPruneData(db);
+            sUpdatingDB = false;
+
+            return null;
+        }
+
+        private ContentValues getContentValues(String word1, String word2, String locale) {
+            ContentValues values = new ContentValues(3);
+            values.put(MAIN_COLUMN_WORD1, word1);
+            values.put(MAIN_COLUMN_WORD2, word2);
+            values.put(MAIN_COLUMN_LOCALE, locale);
+            return values;
+        }
+
+        private ContentValues getFrequencyContentValues(int pairId, int frequency) {
+           ContentValues values = new ContentValues(2);
+           values.put(FREQ_COLUMN_PAIR_ID, pairId);
+           values.put(FREQ_COLUMN_FREQUENCY, frequency);
+           return values;
+        }
+    }
+
+}
diff --git a/tests/src/com/android/inputmethod/latin/tests/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
similarity index 68%
rename from tests/src/com/android/inputmethod/latin/tests/SuggestHelper.java
rename to tests/src/com/android/inputmethod/latin/SuggestHelper.java
index 107f04c..759bfa1 100644
--- a/tests/src/com/android/inputmethod/latin/tests/SuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
@@ -14,13 +14,13 @@
  * the License.
  */
 
-package com.android.inputmethod.latin.tests;
+package com.android.inputmethod.latin;
 
 import android.content.Context;
-import android.test.AndroidTestCase;
 import android.text.TextUtils;
 import android.util.Log;
 import com.android.inputmethod.latin.Suggest;
+import com.android.inputmethod.latin.UserBigramDictionary;
 import com.android.inputmethod.latin.WordComposer;
 
 import java.io.IOException;
@@ -29,28 +29,32 @@
 import java.nio.ByteOrder;
 import java.nio.channels.Channels;
 import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
 
 public class SuggestHelper {
     private Suggest mSuggest;
+    private UserBigramDictionary mUserBigram;
     private final String TAG;
 
+    /** Uses main dictionary only **/
     public SuggestHelper(String tag, Context context, int[] resId) {
         TAG = tag;
-        InputStream[] res = null;
+        InputStream[] is = null;
         try {
             // merging separated dictionary into one if dictionary is separated
             int total = 0;
-            res = new InputStream[resId.length];
+            is = new InputStream[resId.length];
             for (int i = 0; i < resId.length; i++) {
-                res[i] = context.getResources().openRawResource(resId[i]);
-                total += res[i].available();
+                is[i] = context.getResources().openRawResource(resId[i]);
+                total += is[i].available();
             }
 
             ByteBuffer byteBuffer =
                 ByteBuffer.allocateDirect(total).order(ByteOrder.nativeOrder());
             int got = 0;
             for (int i = 0; i < resId.length; i++) {
-                 got += Channels.newChannel(res[i]).read(byteBuffer);
+                 got += Channels.newChannel(is[i]).read(byteBuffer);
             }
             if (got != total) {
                 Log.w(TAG, "Read " + got + " bytes, expected " + total);
@@ -62,8 +66,10 @@
             Log.w(TAG, "No available memory for binary dictionary");
         } finally {
             try {
-                for (int i = 0;i < res.length; i++) {
-                    res[i].close();
+                if (is != null) {
+                    for (int i = 0; i < is.length; i++) {
+                        is[i].close();
+                    }
                 }
             } catch (IOException e) {
                 Log.w(TAG, "Failed to close input stream");
@@ -73,6 +79,27 @@
         mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM);
     }
 
+    /** Uses both main dictionary and user-bigram dictionary **/
+    public SuggestHelper(String tag, Context context, int[] resId, int userBigramMax,
+            int userBigramDelete) {
+        this(tag, context, resId);
+        mUserBigram = new UserBigramDictionary(context, null, Locale.US.toString(),
+                Suggest.DIC_USER);
+        mUserBigram.setDatabaseMax(userBigramMax);
+        mUserBigram.setDatabaseDelete(userBigramDelete);
+        mSuggest.setUserBigramDictionary(mUserBigram);
+    }
+
+    void changeUserBigramLocale(Context context, Locale locale) {
+        if (mUserBigram != null) {
+            flushUserBigrams();
+            mUserBigram.close();
+            mUserBigram = new UserBigramDictionary(context, null, locale.toString(),
+                    Suggest.DIC_USER);
+            mSuggest.setUserBigramDictionary(mUserBigram);
+        }
+    }
+
     private WordComposer createWordComposer(CharSequence s) {
         WordComposer word = new WordComposer();
         for (int i = 0; i < s.length(); i++) {
@@ -125,8 +152,8 @@
     }
 
     private void getBigramSuggestions(CharSequence previous, CharSequence typed) {
-        if(!TextUtils.isEmpty(previous) && (typed.length() > 1)) {
-            WordComposer firstChar = createWordComposer(typed.charAt(0) + "");
+        if (!TextUtils.isEmpty(previous) && (typed.length() > 1)) {
+            WordComposer firstChar = createWordComposer(Character.toString(typed.charAt(0)));
             mSuggest.getSuggestions(null, firstChar, false, previous);
         }
     }
@@ -162,6 +189,54 @@
         return mSuggest.isValidWord(typed);
     }
 
+    boolean isUserBigramSuggestion(CharSequence previous, char typed,
+           CharSequence expected) {
+        WordComposer word = createWordComposer(Character.toString(typed));
+
+        if (mUserBigram == null) return false;
+
+        flushUserBigrams();
+        if (!TextUtils.isEmpty(previous) && !TextUtils.isEmpty(Character.toString(typed))) {
+            WordComposer firstChar = createWordComposer(Character.toString(typed));
+            mSuggest.getSuggestions(null, firstChar, false, previous);
+            boolean reloading = mUserBigram.reloadDictionaryIfRequired();
+            if (reloading) mUserBigram.waitForDictionaryLoading();
+            mUserBigram.getBigrams(firstChar, previous, mSuggest, null);
+        }
+
+        List<CharSequence> suggestions = mSuggest.mBigramSuggestions;
+        for (int i = 0; i < suggestions.size(); i++) {
+            if (TextUtils.equals(suggestions.get(i), expected)) return true;
+        }
+
+        return false;
+    }
+
+    void addToUserBigram(String sentence) {
+        StringTokenizer st = new StringTokenizer(sentence);
+        String previous = null;
+        while (st.hasMoreTokens()) {
+            String current = st.nextToken();
+            if (previous != null) {
+                addToUserBigram(new String[] {previous, current});
+            }
+            previous = current;
+        }
+    }
+
+    void addToUserBigram(String[] pair) {
+        if (mUserBigram != null && pair.length == 2) {
+            mUserBigram.addBigrams(pair[0], pair[1]);
+        }
+    }
+
+    void flushUserBigrams() {
+        if (mUserBigram != null) {
+            mUserBigram.flushPendingWrites();
+            mUserBigram.waitUntilUpdateDBDone();
+        }
+    }
+
     final int[][] adjacents = {
                                {'a','s','w','q',-1},
                                {'b','h','v','n','g','j',-1},
diff --git a/tests/src/com/android/inputmethod/latin/tests/SuggestPerformanceTests.java b/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java
similarity index 96%
rename from tests/src/com/android/inputmethod/latin/tests/SuggestPerformanceTests.java
rename to tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java
index 473c440..7eb66d5 100644
--- a/tests/src/com/android/inputmethod/latin/tests/SuggestPerformanceTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestPerformanceTests.java
@@ -14,16 +14,15 @@
  * the License.
  */
 
-package com.android.inputmethod.latin.tests;
+package com.android.inputmethod.latin;
 
 import android.test.AndroidTestCase;
 import android.util.Log;
-
+import com.android.inputmethod.latin.tests.R;
 import java.io.InputStreamReader;
 import java.io.InputStream;
 import java.io.BufferedReader;
 import java.util.StringTokenizer;
-import java.util.regex.Pattern;
 
 public class SuggestPerformanceTests extends AndroidTestCase {
     private static final String TAG = "SuggestPerformanceTests";
@@ -122,6 +121,6 @@
      * Check the log for detail
      */
     public void testSuggestPerformance() {
-        assertTrue(runText(false) < runText(true));
+        assertTrue(runText(false) <= runText(true));
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/tests/SuggestTests.java b/tests/src/com/android/inputmethod/latin/SuggestTests.java
similarity index 98%
rename from tests/src/com/android/inputmethod/latin/tests/SuggestTests.java
rename to tests/src/com/android/inputmethod/latin/SuggestTests.java
index a42422b..8463ed3 100644
--- a/tests/src/com/android/inputmethod/latin/tests/SuggestTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestTests.java
@@ -14,10 +14,10 @@
  * the License.
  */
 
-package com.android.inputmethod.latin.tests;
+package com.android.inputmethod.latin;
 
 import android.test.AndroidTestCase;
-import android.util.Log;
+import com.android.inputmethod.latin.tests.R;
 
 public class SuggestTests extends AndroidTestCase {
     private static final String TAG = "SuggestTests";
diff --git a/tests/src/com/android/inputmethod/latin/UserBigramTests.java b/tests/src/com/android/inputmethod/latin/UserBigramTests.java
new file mode 100644
index 0000000..cbf7bd8
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/UserBigramTests.java
@@ -0,0 +1,100 @@
+/*
+ * 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 com.android.inputmethod.latin.tests.R;
+import java.util.Locale;
+
+public class UserBigramTests extends AndroidTestCase {
+    private static final String TAG = "UserBigramTests";
+
+    private static final int SUGGESTION_STARTS = 6;
+    private static final int MAX_DATA = 20;
+    private static final int DELETE_DATA = 10;
+
+    private SuggestHelper sh;
+
+    @Override
+    protected void setUp() {
+        int[] resId = new int[] { R.raw.test };
+        sh = new SuggestHelper(TAG, getTestContext(), resId, MAX_DATA, DELETE_DATA);
+    }
+
+    /************************** Tests ************************/
+
+    /**
+     * Test suggestion started at right time
+     */
+    public void testUserBigram() {
+        for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(pair1);
+        for (int i = 0; i < (SUGGESTION_STARTS - 1); i++) sh.addToUserBigram(pair2);
+
+        assertTrue(sh.isUserBigramSuggestion("user", 'b', "bigram"));
+        assertFalse(sh.isUserBigramSuggestion("android", 'p', "platform"));
+    }
+
+    /**
+     * Test loading correct (locale) bigrams
+     */
+    public void testOpenAndClose() {
+        for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(pair1);
+        assertTrue(sh.isUserBigramSuggestion("user", 'b', "bigram"));
+
+        // change to fr_FR
+        sh.changeUserBigramLocale(getTestContext(), Locale.FRANCE);
+        for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(pair3);
+        assertTrue(sh.isUserBigramSuggestion("locale", 'f', "france"));
+        assertFalse(sh.isUserBigramSuggestion("user", 'b', "bigram"));
+
+        // change back to en_US
+        sh.changeUserBigramLocale(getTestContext(), Locale.US);
+        assertFalse(sh.isUserBigramSuggestion("locale", 'f', "france"));
+        assertTrue(sh.isUserBigramSuggestion("user", 'b', "bigram"));
+    }
+
+    /**
+     * Test data gets pruned when it is over maximum
+     */
+    public void testPruningData() {
+        for (int i = 0; i < SUGGESTION_STARTS; i++) sh.addToUserBigram(sentence0);
+        sh.flushUserBigrams();
+        assertTrue(sh.isUserBigramSuggestion("Hello", 'w', "world"));
+
+        sh.addToUserBigram(sentence1);
+        sh.addToUserBigram(sentence2);
+        assertTrue(sh.isUserBigramSuggestion("Hello", 'w', "world"));
+
+        // pruning should happen
+        sh.addToUserBigram(sentence3);
+        sh.addToUserBigram(sentence4);
+
+        // trying to reopen database to check pruning happened in database
+        sh.changeUserBigramLocale(getTestContext(), Locale.US);
+        assertFalse(sh.isUserBigramSuggestion("Hello", 'w', "world"));
+    }
+
+    final String[] pair1 = new String[] {"user", "bigram"};
+    final String[] pair2 = new String[] {"android","platform"};
+    final String[] pair3 = new String[] {"locale", "france"};
+    final String sentence0 = "Hello world";
+    final String sentence1 = "This is a test for user input based bigram";
+    final String sentence2 = "It learns phrases that contain both dictionary and nondictionary "
+            + "words";
+    final String sentence3 = "This should give better suggestions than the previous version";
+    final String sentence4 = "Android stock keyboard is improving";
+}