diff --git a/dictionaries/en_gb_wordlist.xml b/dictionaries/en_gb_wordlist.xml
index c2af46e1d604081f6a7f508debb7621d02ae136d..09078ae0b4656eaf7a753b7a4a38f6784b74f8ba 100644
--- a/dictionaries/en_gb_wordlist.xml
+++ b/dictionaries/en_gb_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="en_GB" description="English (UK)" date="1340038724" version="16">
+<wordlist locale="en_GB" description="English (UK)" date="1340965760" version="17">
  <w f="222" flags="">the</w>
  <w f="214" flags="">of</w>
  <w f="212" flags="">and</w>
@@ -256,7 +256,6 @@
  <w f="155" flags="">national</w>
  <w f="155" flags="">nice</w>
  <w f="155" flags="">non</w>
- <w f="155" flags="">north</w>
  <w f="155" flags="">period</w>
  <w f="155" flags="">son</w>
  <w f="155" flags="">south</w>
@@ -283,7 +282,6 @@
  <w f="154" flags="">present</w>
  <w f="154" flags="">produced</w>
  <w f="154" flags="">record</w>
- <w f="154" flags="">role</w>
  <w f="154" flags="">six</w>
  <w f="154" flags="">species</w>
  <w f="154" flags="">started</w>
@@ -607,6 +605,7 @@
  <w f="145" flags="">move</w>
  <w f="145" flags="">natural</w>
  <w f="145" flags="">network</w>
+ <w f="145" flags="">north</w>
  <w f="145" flags="">northern</w>
  <w f="145" flags="">novel</w>
  <w f="145" flags="">numerous</w>
@@ -708,6 +707,7 @@
  <w f="144" flags="">rate</w>
  <w f="144" flags="">recent</w>
  <w f="144" flags="">remains</w>
+ <w f="144" flags="">role</w>
  <w f="144" flags="">seat</w>
  <w f="144" flags="">self</w>
  <w f="144" flags="">shown</w>
@@ -13520,7 +13520,6 @@
  <w f="97" flags="">Kay</w>
  <w f="97" flags="">Klein</w>
  <w f="97" flags="">Kuwait</w>
- <w f="97" flags="">Lang</w>
  <w f="97" flags="">Leigh</w>
  <w f="97" flags="">Leipzig</w>
  <w f="97" flags="">Lennon</w>
@@ -14169,7 +14168,6 @@
  <w f="96" flags="">MacLeod</w>
  <w f="96" flags="">Mafia</w>
  <w f="96" flags="">Maharashtra</w>
- <w f="96" flags="">Marina</w>
  <w f="96" flags="">McCall</w>
  <w f="96" flags="">McClellan</w>
  <w f="96" flags="">McGuire</w>
@@ -15902,7 +15900,6 @@
  <w f="94" flags="">leakage</w>
  <w f="94" flags="">leaks</w>
  <w f="94" flags="">lecturing</w>
- <w f="94" flags="">lesbians</w>
  <w f="94" flags="">licences</w>
  <w f="94" flags="">life's</w>
  <w f="94" flags="">lifeboat</w>
@@ -16780,7 +16777,6 @@
  <w f="93" flags="">sclerosis</w>
  <w f="93" flags="">scream</w>
  <w f="93" flags="">screenplays</w>
- <w f="93" flags="">screws</w>
  <w f="93" flags="">seaport</w>
  <w f="93" flags="">seawater</w>
  <w f="93" flags="">secretaries</w>
@@ -29553,7 +29549,6 @@
  <w f="79" flags="">Getty</w>
  <w f="79" flags="">Gleason</w>
  <w f="79" flags="">Godwin</w>
- <w f="79" flags="">Gotha</w>
  <w f="79" flags="">Grantham</w>
  <w f="79" flags="">Greenpeace</w>
  <w f="79" flags="">Grenoble</w>
@@ -32722,7 +32717,6 @@
  <w f="77" flags="">leeward</w>
  <w f="77" flags="">lengthwise</w>
  <w f="77" flags="">lentils</w>
- <w f="77" flags="">lesbianism</w>
  <w f="77" flags="">leveraging</w>
  <w f="77" flags="">lib</w>
  <w f="77" flags="">libertarianism</w>
@@ -49865,7 +49859,6 @@
  <w f="64" flags="abbreviation">ECW's</w>
  <w f="64" flags="abbreviation">EEOC</w>
  <w f="64" flags="abbreviation">EKG</w>
- <w f="64" flags="abbreviation">ENS</w>
  <w f="64" flags="abbreviation">ESOL</w>
  <w f="64" flags="">Edgeworth</w>
  <w f="64" flags="">Edirne</w>
@@ -54575,7 +54568,6 @@
  <w f="61" flags="">Hersey</w>
  <w f="61" flags="">Hiatt</w>
  <w f="61" flags="">Himmler's</w>
- <w f="61" flags="">Hoke</w>
  <w f="61" flags="">Hormuz</w>
  <w f="61" flags="">Hosea</w>
  <w f="61" flags="">Hubli</w>
@@ -89915,7 +89907,6 @@
  <w f="38" flags="">Hally</w>
  <w f="38" flags="">Harpo's</w>
  <w f="38" flags="">Higbee's</w>
- <w f="38" flags="">Hoke's</w>
  <w f="38" flags="">Honeywell's</w>
  <w f="38" flags="">Horatian</w>
  <w f="38" flags="">Iago's</w>
@@ -109454,7 +109445,6 @@
  <w f="25" flags="">leets</w>
  <w f="25" flags="">legitimism</w>
  <w f="25" flags="">leopardskin</w>
- <w f="25" flags="">lesbian's</w>
  <w f="25" flags="">lessee's</w>
  <w f="25" flags="">lethargically</w>
  <w f="25" flags="">libber</w>
@@ -112568,7 +112558,6 @@
  <w f="23" flags="">pickerels</w>
  <w f="23" flags="">piecers</w>
  <w f="23" flags="">pigmenting</w>
- <w f="23" flags="">pill's</w>
  <w f="23" flags="">pilled</w>
  <w f="23" flags="">pillorying</w>
  <w f="23" flags="">pinked</w>
@@ -117332,7 +117321,6 @@
  <w f="18" flags="">Hinsdale's</w>
  <w f="18" flags="">Hispaniola's</w>
  <w f="18" flags="">Hohenzollern's</w>
- <w f="18" flags="">Hokes</w>
  <w f="18" flags="">Horst's</w>
  <w f="18" flags="">Housecat's</w>
  <w f="18" flags="">Hughie's</w>
@@ -155568,6 +155556,7 @@
  <w f="0" flags="">XP</w>
  <w f="0" flags="offensive">Yoni's</w>
  <w f="0" flags="">acct</w>
+ <w f="0">admin</w>
  <w f="0" flags="n">adult</w>
  <w f="0" flags="medical">adulteress</w>
  <w f="0" flags="medical">adulteresses</w>
@@ -156092,6 +156081,9 @@
  <w f="0" flags="">lei</w>
  <w f="0" flags="">lem</w>
  <w f="0" flags="n">lesbian</w>
+ <w f="0" flags="">lesbian's</w>
+ <w f="0" flags="">lesbianism</w>
+ <w f="0" flags="">lesbians</w>
  <w f="0" flags="offensive">letch</w>
  <w f="0" flags="n">libido</w>
  <w f="0" flags="s">librium</w>
@@ -156267,6 +156259,7 @@
  <w f="0" flags="medical">phosphaturia</w>
  <w f="0" flags="medical">phosphaturic</w>
  <w f="0" flags="s">pill</w>
+ <w f="0" flags="">pill's</w>
  <w f="0" flags="s">pills</w>
  <w f="0" flags="offensive">pimp</w>
  <w f="0" flags="offensive">pimp's</w>
@@ -156428,6 +156421,7 @@
  <w f="0" flags="r">screw</w>
  <w f="0" flags="n">screwed</w>
  <w f="0" flags="n">screwing</w>
+ <w f="0" flags="">screws</w>
  <w f="0" flags="medical">scrota</w>
  <w f="0" flags="medical">scrotal</w>
  <w f="0" flags="medical">scrotum</w>
@@ -156641,6 +156635,7 @@
  <w f="0" flags="babytalk">twat</w>
  <w f="0" flags="babytalk">twats</w>
  <w f="0" flags="">twit</w>
+ <w f="0">ui</w>
  <w f="0">ull</w>
  <w f="0" flags="babytalk">underclothing</w>
  <w f="0" flags="babytalk">underwear</w>
@@ -156747,6 +156742,7 @@
  <w f="0" flags="medical">uterus</w>
  <w f="0" flags="medical">uterus's</w>
  <w f="0" flags="medical">uteruses</w>
+ <w f="0">ux</w>
  <w f="0" flags="medical">vagina</w>
  <w f="0" flags="medical">vagina's</w>
  <w f="0" flags="medical">vaginae</w>
diff --git a/dictionaries/en_us_wordlist.xml b/dictionaries/en_us_wordlist.xml
index 3cafbd7863be4791705a453071dcfa2a4f5e6c67..0b158f55316b5f23cddc149b4951e5c2414b3a09 100644
--- a/dictionaries/en_us_wordlist.xml
+++ b/dictionaries/en_us_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="en_US" description="English (US)" date="1340038693" version="16">
+<wordlist locale="en_US" description="English (US)" date="1340965726" version="17">
  <w f="222" flags="">the</w>
  <w f="214" flags="">of</w>
  <w f="212" flags="">and</w>
@@ -255,7 +255,6 @@
  <w f="155" flags="">national</w>
  <w f="155" flags="">nice</w>
  <w f="155" flags="">non</w>
- <w f="155" flags="">north</w>
  <w f="155" flags="">period</w>
  <w f="155" flags="">son</w>
  <w f="155" flags="">south</w>
@@ -282,7 +281,6 @@
  <w f="154" flags="">present</w>
  <w f="154" flags="">produced</w>
  <w f="154" flags="">record</w>
- <w f="154" flags="">role</w>
  <w f="154" flags="">six</w>
  <w f="154" flags="">species</w>
  <w f="154" flags="">started</w>
@@ -587,7 +585,6 @@
  <w f="145" flags="">July</w>
  <w f="145" flags="">June</w>
  <w f="145" flags="">March</w>
- <w f="145" flags="">North</w>
  <w f="145" flags="">October</w>
  <w f="145" flags="">active</w>
  <w f="145" flags="">always</w>
@@ -614,6 +611,7 @@
  <w f="145" flags="">move</w>
  <w f="145" flags="">natural</w>
  <w f="145" flags="">network</w>
+ <w f="145" flags="">north</w>
  <w f="145" flags="">northern</w>
  <w f="145" flags="">novel</w>
  <w f="145" flags="">numerous</w>
@@ -717,6 +715,7 @@
  <w f="144" flags="">rate</w>
  <w f="144" flags="">recent</w>
  <w f="144" flags="">remains</w>
+ <w f="144" flags="">role</w>
  <w f="144" flags="">seat</w>
  <w f="144" flags="">self</w>
  <w f="144" flags="">shown</w>
@@ -12069,6 +12068,7 @@
  <w f="100" flags="">Nash</w>
  <w f="100" flags="">Newark</w>
  <w f="100" flags="">Norse</w>
+ <w f="100" flags="">North</w>
  <w f="100" flags="">Norton</w>
  <w f="100" flags="">Norwich</w>
  <w f="100" flags="">Okinawa</w>
@@ -13996,7 +13996,6 @@
  <w f="97" flags="">Klein</w>
  <w f="97" flags="">Kuwait</w>
  <w f="97" flags="">Ladies</w>
- <w f="97" flags="">Lang</w>
  <w f="97" flags="">Leigh</w>
  <w f="97" flags="">Leipzig</w>
  <w f="97" flags="">Lennon</w>
@@ -14677,7 +14676,6 @@
  <w f="96" flags="">Madras</w>
  <w f="96" flags="">Mafia</w>
  <w f="96" flags="">Maharashtra</w>
- <w f="96" flags="">Marina</w>
  <w f="96" flags="">Master's</w>
  <w f="96" flags="">McCall</w>
  <w f="96" flags="">McClellan</w>
@@ -16141,7 +16139,6 @@
  <w f="94" flags="">Stratford</w>
  <w f="94" flags="">Strauss</w>
  <w f="94" flags="">Stuttgart</w>
- <w f="94" flags="">Sunshine</w>
  <w f="94" flags="">Suzuki</w>
  <w f="94" flags="">Taiwanese</w>
  <w f="94" flags="">Talbot</w>
@@ -16154,7 +16151,6 @@
  <w f="94" flags="">Tyne</w>
  <w f="94" flags="abbreviation">UNC</w>
  <w f="94" flags="abbreviation">UNICEF</w>
- <w f="94" flags="">UNIX</w>
  <w f="94" flags="abbreviation">USDA</w>
  <w f="94" flags="">Unix</w>
  <w f="94" flags="">Valentine</w>
@@ -16488,7 +16484,6 @@
  <w f="94" flags="">leakage</w>
  <w f="94" flags="">leaks</w>
  <w f="94" flags="">lecturing</w>
- <w f="94" flags="">lesbians</w>
  <w f="94" flags="">leveled</w>
  <w f="94" flags="">life's</w>
  <w f="94" flags="">lifeboat</w>
@@ -17402,7 +17397,6 @@
  <w f="93" flags="">sclerosis</w>
  <w f="93" flags="">scream</w>
  <w f="93" flags="">screenplays</w>
- <w f="93" flags="">screws</w>
  <w f="93" flags="">seaport</w>
  <w f="93" flags="">seawater</w>
  <w f="93" flags="">secretaries</w>
@@ -30682,7 +30676,6 @@
  <w f="79" flags="">Ghats</w>
  <w f="79" flags="">Gleason</w>
  <w f="79" flags="">Godwin</w>
- <w f="79" flags="">Gotha</w>
  <w f="79" flags="">Grantham</w>
  <w f="79" flags="">Greenpeace</w>
  <w f="79" flags="">Grenoble</w>
@@ -33954,7 +33947,6 @@
  <w f="77" flags="">leeward</w>
  <w f="77" flags="">lengthwise</w>
  <w f="77" flags="">lentils</w>
- <w f="77" flags="">lesbianism</w>
  <w f="77" flags="">leveraging</w>
  <w f="77" flags="">lib</w>
  <w f="77" flags="">libertarianism</w>
@@ -92910,7 +92902,6 @@
  <w f="38" flags="">Harpo's</w>
  <w f="38" flags="">Higbee's</w>
  <w f="38">Hipparchus</w>
- <w f="38" flags="">Hoke's</w>
  <w f="38" flags="">Honeywell's</w>
  <w f="38" flags="">Horatian</w>
  <w f="38" flags="">Iago's</w>
@@ -112796,7 +112787,6 @@
  <w f="25" flags="">leets</w>
  <w f="25" flags="">legitimism</w>
  <w f="25" flags="">leopardskin</w>
- <w f="25" flags="">lesbian's</w>
  <w f="25" flags="">lessee's</w>
  <w f="25" flags="">lethargically</w>
  <w f="25" flags="">libber</w>
@@ -115952,7 +115942,6 @@
  <w f="23" flags="">pickerels</w>
  <w f="23" flags="">piecers</w>
  <w f="23" flags="">pigmenting</w>
- <w f="23" flags="">pill's</w>
  <w f="23" flags="">pilled</w>
  <w f="23" flags="">pillorying</w>
  <w f="23" flags="">pinked</w>
@@ -120765,7 +120754,6 @@
  <w f="18" flags="">Hinsdale's</w>
  <w f="18" flags="">Hispaniola's</w>
  <w f="18" flags="">Hohenzollern's</w>
- <w f="18" flags="">Hokes</w>
  <w f="18" flags="">Horst's</w>
  <w f="18" flags="">Housecat's</w>
  <w f="18" flags="">Hughie's</w>
@@ -159318,6 +159306,7 @@
  <w f="0" flags="">XP</w>
  <w f="0" flags="offensive">Yoni's</w>
  <w f="0" flags="">acct</w>
+ <w f="0">admin</w>
  <w f="0" flags="n">adult</w>
  <w f="0" flags="medical">adulteress</w>
  <w f="0" flags="medical">adulteresses</w>
@@ -159849,6 +159838,9 @@
  <w f="0" flags="medical">leching</w>
  <w f="0" flags="">lei</w>
  <w f="0" flags="n">lesbian</w>
+ <w f="0" flags="">lesbian's</w>
+ <w f="0" flags="">lesbianism</w>
+ <w f="0" flags="">lesbians</w>
  <w f="0" flags="offensive">letch</w>
  <w f="0" flags="n">libido</w>
  <w f="0" flags="n">lick</w>
@@ -160024,6 +160016,7 @@
  <w f="0" flags="medical">phosphaturia</w>
  <w f="0" flags="medical">phosphaturic</w>
  <w f="0" flags="s">pill</w>
+ <w f="0" flags="">pill's</w>
  <w f="0" flags="s">pills</w>
  <w f="0" flags="offensive">pimp</w>
  <w f="0" flags="offensive">pimp's</w>
@@ -160183,6 +160176,7 @@
  <w f="0" flags="r">screw</w>
  <w f="0" flags="n">screwed</w>
  <w f="0" flags="n">screwing</w>
+ <w f="0" flags="">screws</w>
  <w f="0" flags="medical">scrota</w>
  <w f="0" flags="medical">scrotal</w>
  <w f="0" flags="medical">scrotum</w>
@@ -160398,6 +160392,7 @@
  <w f="0" flags="babytalk">twat</w>
  <w f="0" flags="babytalk">twats</w>
  <w f="0" flags="">twit</w>
+ <w f="0">ui</w>
  <w f="0">ull</w>
  <w f="0" flags="">ump</w>
  <w f="0" flags="babytalk">underclothing</w>
@@ -160505,6 +160500,7 @@
  <w f="0" flags="medical">uterus</w>
  <w f="0" flags="medical">uterus's</w>
  <w f="0" flags="medical">uteruses</w>
+ <w f="0">ux</w>
  <w f="0" flags="medical">vagina</w>
  <w f="0" flags="medical">vagina's</w>
  <w f="0" flags="medical">vaginae</w>
diff --git a/dictionaries/en_wordlist.xml b/dictionaries/en_wordlist.xml
index 6f594d5a40b92755f1eacdb512e384d21808ec75..c6b3bdc940dd703e21aefcd60a402368990edf55 100644
--- a/dictionaries/en_wordlist.xml
+++ b/dictionaries/en_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="en" description="English" date="1340038727" version="16">
+<wordlist locale="en" description="English" date="1340965763" version="17">
  <w f="222" flags="">the</w>
  <w f="214" flags="">of</w>
  <w f="212" flags="">and</w>
@@ -255,7 +255,6 @@
  <w f="155" flags="">national</w>
  <w f="155" flags="">nice</w>
  <w f="155" flags="">non</w>
- <w f="155" flags="">north</w>
  <w f="155" flags="">period</w>
  <w f="155" flags="">son</w>
  <w f="155" flags="">south</w>
@@ -282,7 +281,6 @@
  <w f="154" flags="">present</w>
  <w f="154" flags="">produced</w>
  <w f="154" flags="">record</w>
- <w f="154" flags="">role</w>
  <w f="154" flags="">six</w>
  <w f="154" flags="">species</w>
  <w f="154" flags="">started</w>
@@ -587,7 +585,6 @@
  <w f="145" flags="">July</w>
  <w f="145" flags="">June</w>
  <w f="145" flags="">March</w>
- <w f="145" flags="">North</w>
  <w f="145" flags="">October</w>
  <w f="145" flags="">active</w>
  <w f="145" flags="">always</w>
@@ -614,6 +611,7 @@
  <w f="145" flags="">move</w>
  <w f="145" flags="">natural</w>
  <w f="145" flags="">network</w>
+ <w f="145" flags="">north</w>
  <w f="145" flags="">northern</w>
  <w f="145" flags="">novel</w>
  <w f="145" flags="">numerous</w>
@@ -718,6 +716,7 @@
  <w f="144" flags="">rate</w>
  <w f="144" flags="">recent</w>
  <w f="144" flags="">remains</w>
+ <w f="144" flags="">role</w>
  <w f="144" flags="">seat</w>
  <w f="144" flags="">self</w>
  <w f="144" flags="">shown</w>
@@ -12162,6 +12161,7 @@
  <w f="100" flags="">Nash</w>
  <w f="100" flags="">Newark</w>
  <w f="100" flags="">Norse</w>
+ <w f="100" flags="">North</w>
  <w f="100" flags="">Norton</w>
  <w f="100" flags="">Norwich</w>
  <w f="100" flags="">Okinawa</w>
@@ -14103,7 +14103,6 @@
  <w f="97" flags="">Klein</w>
  <w f="97" flags="">Kuwait</w>
  <w f="97" flags="">Ladies</w>
- <w f="97" flags="">Lang</w>
  <w f="97" flags="">Leigh</w>
  <w f="97" flags="">Leipzig</w>
  <w f="97" flags="">Lennon</w>
@@ -14792,7 +14791,6 @@
  <w f="96" flags="">Madras</w>
  <w f="96" flags="">Mafia</w>
  <w f="96" flags="">Maharashtra</w>
- <w f="96" flags="">Marina</w>
  <w f="96" flags="">Master's</w>
  <w f="96" flags="">McCall</w>
  <w f="96" flags="">McClellan</w>
@@ -16273,7 +16271,6 @@
  <w f="94" flags="">Stratford</w>
  <w f="94" flags="">Strauss</w>
  <w f="94" flags="">Stuttgart</w>
- <w f="94" flags="">Sunshine</w>
  <w f="94" flags="">Suzuki</w>
  <w f="94" flags="abbreviation">TBS</w>
  <w f="94" flags="">Taiwanese</w>
@@ -16287,7 +16284,6 @@
  <w f="94" flags="">Tyne</w>
  <w f="94" flags="abbreviation">UNC</w>
  <w f="94" flags="abbreviation">UNICEF</w>
- <w f="94" flags="">UNIX</w>
  <w f="94" flags="abbreviation">USDA</w>
  <w f="94" flags="">Unix</w>
  <w f="94" flags="">Valentine</w>
@@ -16624,7 +16620,6 @@
  <w f="94" flags="">leakage</w>
  <w f="94" flags="">leaks</w>
  <w f="94" flags="">lecturing</w>
- <w f="94" flags="">lesbians</w>
  <w f="94" flags="">leveled</w>
  <w f="94" flags="">licences</w>
  <w f="94" flags="">life's</w>
@@ -17555,7 +17550,6 @@
  <w f="93" flags="">sclerosis</w>
  <w f="93" flags="">scream</w>
  <w f="93" flags="">screenplays</w>
- <w f="93" flags="">screws</w>
  <w f="93" flags="">seaport</w>
  <w f="93" flags="">seawater</w>
  <w f="93" flags="">secretaries</w>
@@ -31073,7 +31067,6 @@
  <w f="79" flags="">Ghats</w>
  <w f="79" flags="">Gleason</w>
  <w f="79" flags="">Godwin</w>
- <w f="79" flags="">Gotha</w>
  <w f="79" flags="">Grantham</w>
  <w f="79" flags="">Greenpeace</w>
  <w f="79" flags="">Grenoble</w>
@@ -34402,7 +34395,6 @@
  <w f="77" flags="">leeward</w>
  <w f="77" flags="">lengthwise</w>
  <w f="77" flags="">lentils</w>
- <w f="77" flags="">lesbianism</w>
  <w f="77" flags="">leveraging</w>
  <w f="77" flags="">lib</w>
  <w f="77" flags="">libertarianism</w>
@@ -52519,7 +52511,6 @@
  <w f="64" flags="abbreviation">ECW's</w>
  <w f="64" flags="abbreviation">EEOC</w>
  <w f="64" flags="abbreviation">EKG</w>
- <w f="64" flags="abbreviation">ENS</w>
  <w f="64" flags="abbreviation">ESOL</w>
  <w f="64" flags="">Edgeworth</w>
  <w f="64" flags="">Edirne</w>
@@ -57486,7 +57477,6 @@
  <w f="61" flags="">Hersey</w>
  <w f="61" flags="">Hiatt</w>
  <w f="61" flags="">Himmler's</w>
- <w f="61" flags="">Hoke</w>
  <w f="61" flags="">Hormuz</w>
  <w f="61" flags="">Hosea</w>
  <w f="61" flags="">Hubli</w>
@@ -94993,7 +94983,6 @@
  <w f="38" flags="">Harpo's</w>
  <w f="38" flags="">Higbee's</w>
  <w f="38">Hipparchus</w>
- <w f="38" flags="">Hoke's</w>
  <w f="38" flags="">Honeywell's</w>
  <w f="38" flags="">Horatian</w>
  <w f="38" flags="">Iago's</w>
@@ -115756,7 +115745,6 @@
  <w f="25" flags="">leets</w>
  <w f="25" flags="">legitimism</w>
  <w f="25" flags="">leopardskin</w>
- <w f="25" flags="">lesbian's</w>
  <w f="25" flags="">lessee's</w>
  <w f="25" flags="">lethargically</w>
  <w f="25" flags="">libber</w>
@@ -119045,7 +119033,6 @@
  <w f="23" flags="">pickerels</w>
  <w f="23" flags="">piecers</w>
  <w f="23" flags="">pigmenting</w>
- <w f="23" flags="">pill's</w>
  <w f="23" flags="">pilled</w>
  <w f="23" flags="">pillorying</w>
  <w f="23" flags="">pinked</w>
@@ -124070,7 +124057,6 @@
  <w f="18" flags="">Hinsdale's</w>
  <w f="18" flags="">Hispaniola's</w>
  <w f="18" flags="">Hohenzollern's</w>
- <w f="18" flags="">Hokes</w>
  <w f="18" flags="">Horst's</w>
  <w f="18" flags="">Housecat's</w>
  <w f="18" flags="">Hughie's</w>
@@ -164106,6 +164092,7 @@
  <w f="0" flags="">XP</w>
  <w f="0" flags="offensive">Yoni's</w>
  <w f="0" flags="">acct</w>
+ <w f="0">admin</w>
  <w f="0" flags="n">adult</w>
  <w f="0" flags="medical">adulteress</w>
  <w f="0" flags="medical">adulteresses</w>
@@ -164656,6 +164643,9 @@
  <w f="0" flags="">lei</w>
  <w f="0" flags="">lem</w>
  <w f="0" flags="n">lesbian</w>
+ <w f="0" flags="">lesbian's</w>
+ <w f="0" flags="">lesbianism</w>
+ <w f="0" flags="">lesbians</w>
  <w f="0" flags="offensive">letch</w>
  <w f="0" flags="n">libido</w>
  <w f="0" flags="s">librium</w>
@@ -164842,6 +164832,7 @@
  <w f="0" flags="medical">phosphaturia</w>
  <w f="0" flags="medical">phosphaturic</w>
  <w f="0" flags="s">pill</w>
+ <w f="0" flags="">pill's</w>
  <w f="0" flags="s">pills</w>
  <w f="0" flags="offensive">pimp</w>
  <w f="0" flags="offensive">pimp's</w>
@@ -165004,6 +164995,7 @@
  <w f="0" flags="r">screw</w>
  <w f="0" flags="n">screwed</w>
  <w f="0" flags="n">screwing</w>
+ <w f="0" flags="">screws</w>
  <w f="0" flags="medical">scrota</w>
  <w f="0" flags="medical">scrotal</w>
  <w f="0" flags="medical">scrotum</w>
@@ -165226,6 +165218,7 @@
  <w f="0" flags="babytalk">twat</w>
  <w f="0" flags="babytalk">twats</w>
  <w f="0" flags="">twit</w>
+ <w f="0">ui</w>
  <w f="0">ull</w>
  <w f="0" flags="">ump</w>
  <w f="0" flags="babytalk">underclothing</w>
@@ -165335,6 +165328,7 @@
  <w f="0" flags="medical">uterus</w>
  <w f="0" flags="medical">uterus's</w>
  <w f="0" flags="medical">uteruses</w>
+ <w f="0">ux</w>
  <w f="0" flags="medical">vagina</w>
  <w f="0" flags="medical">vagina's</w>
  <w f="0" flags="medical">vaginae</w>
diff --git a/dictionaries/fr_wordlist.xml b/dictionaries/fr_wordlist.xml
index 39909885c22d480b709043984f0acc4cc5d75b2f..6053f4843fe2e57ac01b3b9a0b4e367f25fcbdc2 100644
--- a/dictionaries/fr_wordlist.xml
+++ b/dictionaries/fr_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="fr" description="Français" date="1339787661" version="15" options="french_ligature_processing">
+<wordlist locale="fr" description="Français" date="1340965148" version="17" options="french_ligature_processing">
  <w f="209" flags="">de</w>
  <w f="200" flags="">la</w>
  <w f="197" flags="">et</w>
@@ -1069,6 +1069,7 @@
  <w f="125" flags="">finit</w>
  <w f="125" flags="">fleuve</w>
  <w f="125" flags="">fondateur</w>
+ <w f="125">généralement</w>
  <w f="125" flags="">hors</w>
  <w f="125" flags="">ici</w>
  <w f="125" flags="">importantes</w>
@@ -13168,7 +13169,6 @@
  <w f="90" flags="">play-offs</w>
  <w f="90" flags="">plaça</w>
  <w f="90" flags="">plonger</w>
- <w f="90" flags="">pole</w>
  <w f="90" flags="">polonaises</w>
  <w f="90" flags="">polymères</w>
  <w f="90" flags="">popularisé</w>
@@ -15098,7 +15098,6 @@
  <w f="87" flags="">donneur</w>
  <w f="87" flags="">dorés</w>
  <w f="87" flags="">doucement</w>
- <w f="87" flags="">doyenné</w>
  <w f="87" flags="">drames</w>
  <w f="87" flags="">dualité</w>
  <w f="87" flags="">ducale</w>
@@ -20845,7 +20844,6 @@
  <w f="81" flags="">matérialisme</w>
  <w f="81" flags="">mauve</w>
  <w f="81" flags="">maximiser</w>
- <w f="81" flags="">media</w>
  <w f="81" flags="">melon</w>
  <w f="81" flags="">mendiants</w>
  <w f="81" flags="">menuiserie</w>
@@ -21702,7 +21700,6 @@
  <w f="80" flags="">gallo-romains</w>
  <w f="80" flags="">galop</w>
  <w f="80" flags="">gangster</w>
- <w f="80" flags="">general</w>
  <w f="80" flags="">gentilé</w>
  <w f="80" flags="">gewurztraminer</w>
  <w f="80" flags="">gisant</w>
@@ -24213,7 +24210,6 @@
  <w f="78" flags="">mythologies</w>
  <w f="78" flags="">mâchicoulis</w>
  <w f="78" flags="">méconnue</w>
- <w f="78" flags="">médina</w>
  <w f="78" flags="">mésopotamienne</w>
  <w f="78" flags="">métriques</w>
  <w f="78" flags="">n'apprécie</w>
@@ -26343,7 +26339,6 @@
  <w f="76" flags="">graphème</w>
  <w f="76" flags="">gravitationnelles</w>
  <w f="76" flags="">greffer</w>
- <w f="76" flags="">guérilleros</w>
  <w f="76" flags="">gèle</w>
  <w f="76" flags="">génitales</w>
  <w f="76" flags="">généalogiques</w>
@@ -31797,7 +31792,6 @@
  <w f="72" flags="">gouvernait</w>
  <w f="72" flags="">gouvernant</w>
  <w f="72" flags="">goéland</w>
- <w f="72" flags="">grace</w>
  <w f="72" flags="">groove</w>
  <w f="72" flags="">gymnastes</w>
  <w f="72" flags="">génomes</w>
@@ -32178,7 +32172,6 @@
  <w f="72" flags="">polders</w>
  <w f="72" flags="">poliomyélite</w>
  <w f="72" flags="">polychromie</w>
- <w f="72" flags="">polynomiale</w>
  <w f="72" flags="">polyvalents</w>
  <w f="72" flags="">pondus</w>
  <w f="72" flags="">pool</w>
@@ -33103,7 +33096,6 @@
  <w f="71" flags="">d'Austin</w>
  <w f="71" flags="">d'Avalon</w>
  <w f="71" flags="">d'Azov</w>
- <w f="71" flags="">d'Aïn</w>
  <w f="71" flags="">d'Emily</w>
  <w f="71" flags="">d'Esther</w>
  <w f="71" flags="">d'Halicarnasse</w>
@@ -33402,7 +33394,6 @@
  <w f="71" flags="">imaginés</w>
  <w f="71" flags="">immigrant</w>
  <w f="71" flags="">imparfait</w>
- <w f="71" flags="">imperium</w>
  <w f="71" flags="">implicites</w>
  <w f="71" flags="">importateur</w>
  <w f="71" flags="">imposable</w>
@@ -33808,7 +33799,6 @@
  <w f="71" flags="">rasées</w>
  <w f="71" flags="">rationaliser</w>
  <w f="71" flags="">rayés</w>
- <w f="71" flags="">real</w>
  <w f="71" flags="">rebaptiser</w>
  <w f="71" flags="">rebâti</w>
  <w f="71" flags="">recensant</w>
@@ -34659,7 +34649,6 @@
  <w f="70" flags="">cénotaphe</w>
  <w f="70" flags="">d'Achaïe</w>
  <w f="70" flags="">d'Agrippa</w>
- <w f="70" flags="">d'Al-Qaida</w>
  <w f="70" flags="">d'Alabama</w>
  <w f="70" flags="">d'Albon</w>
  <w f="70" flags="">d'Alessandro</w>
@@ -34674,7 +34663,6 @@
  <w f="70" flags="">d'Argos</w>
  <w f="70" flags="">d'Assouan</w>
  <w f="70" flags="">d'Avaugour</w>
- <w f="70" flags="">d'Avila</w>
  <w f="70" flags="">d'Azincourt</w>
  <w f="70" flags="">d'East</w>
  <w f="70" flags="">d'Edmund</w>
@@ -34788,7 +34776,6 @@
  <w f="70" flags="">diva</w>
  <w f="70" flags="">diverge</w>
  <w f="70" flags="">divergents</w>
- <w f="70" flags="">djebel</w>
  <w f="70" flags="">dominical</w>
  <w f="70" flags="">dopamine</w>
  <w f="70" flags="">dopé</w>
@@ -36252,7 +36239,6 @@
  <w f="69" flags="">concevant</w>
  <w f="69" flags="">concurrencée</w>
  <w f="69" flags="">condense</w>
- <w f="69" flags="">condottiere</w>
  <w f="69" flags="">confidente</w>
  <w f="69" flags="">confine</w>
  <w f="69" flags="">conjonctif</w>
@@ -36274,7 +36260,6 @@
  <w f="69" flags="">coqueluche</w>
  <w f="69" flags="">corda</w>
  <w f="69" flags="">cordiales</w>
- <w f="69" flags="">core</w>
  <w f="69" flags="">corpulence</w>
  <w f="69" flags="">corrosif</w>
  <w f="69" flags="">cottage</w>
@@ -40119,7 +40104,6 @@
  <w f="67" flags="">l'Estrie</w>
  <w f="67" flags="abbreviation">l'IFK</w>
  <w f="67" flags="abbreviation">l'INSEP</w>
- <w f="67" flags="">l'Imperial</w>
  <w f="67" flags="">l'Indien</w>
  <w f="67" flags="">l'Istrie</w>
  <w f="67" flags="abbreviation">l'OSCE</w>
@@ -40246,7 +40230,6 @@
  <w f="67" flags="">mayonnaise</w>
  <w f="67" flags="">maîtrisait</w>
  <w f="67" flags="">maîtrises</w>
- <w f="67" flags="">medium</w>
  <w f="67" flags="">melons</w>
  <w f="67" flags="">membranaires</w>
  <w f="67" flags="">menottes</w>
@@ -41573,7 +41556,6 @@
  <w f="66" flags="">d'Auxonne</w>
  <w f="66" flags="">d'Avellino</w>
  <w f="66" flags="">d'Eddy</w>
- <w f="66" flags="">d'Eden</w>
  <w f="66" flags="">d'Erich</w>
  <w f="66" flags="">d'Eschyle</w>
  <w f="66" flags="">d'Essen</w>
@@ -42181,7 +42163,6 @@
  <w f="66" flags="">mazout</w>
  <w f="66" flags="">maçonné</w>
  <w f="66" flags="">mec</w>
- <w f="66" flags="">medias</w>
  <w f="66" flags="">menaçants</w>
  <w f="66" flags="">mensurations</w>
  <w f="66" flags="">merchandising</w>
@@ -42343,7 +42324,6 @@
  <w f="66" flags="">plénipotentiaires</w>
  <w f="66" flags="">pléthore</w>
  <w f="66" flags="">poignarder</w>
- <w f="66" flags="">polynomial</w>
  <w f="66" flags="">polynésiens</w>
  <w f="66" flags="">pont-canal</w>
  <w f="66" flags="">popularisa</w>
@@ -44095,7 +44075,6 @@
  <w f="65" flags="">manipulent</w>
  <w f="65" flags="">manquèrent</w>
  <w f="65" flags="">manqués</w>
- <w f="65" flags="">maqam</w>
  <w f="65" flags="">marchaient</w>
  <w f="65" flags="">marginalisé</w>
  <w f="65" flags="">marre</w>
@@ -44231,7 +44210,6 @@
  <w f="65" flags="">pensais</w>
  <w f="65" flags="">pensante</w>
  <w f="65" flags="">perdrait</w>
- <w f="65" flags="">perestroïka</w>
  <w f="65" flags="">perfide</w>
  <w f="65" flags="">perméables</w>
  <w f="65" flags="">perpétuant</w>
@@ -45576,7 +45554,6 @@
  <w f="64" flags="">dormance</w>
  <w f="64" flags="">dormi</w>
  <w f="64" flags="">doublent</w>
- <w f="64" flags="">doyennés</w>
  <w f="64" flags="">dragueur</w>
  <w f="64" flags="">dragueurs</w>
  <w f="64" flags="">drainées</w>
@@ -45803,7 +45780,6 @@
  <w f="64" flags="">herbicide</w>
  <w f="64" flags="">heurtèrent</w>
  <w f="64" flags="">hiboux</w>
- <w f="64" flags="">hindî</w>
  <w f="64" flags="">hiragana</w>
  <w f="64" flags="">hivernaux</w>
  <w f="64" flags="">hivernent</w>
@@ -46826,6 +46802,7 @@
  <w f="63" flags="">Dyck</w>
  <w f="63" flags="">Délos</w>
  <w f="63" flags="">Eaton</w>
+ <w f="63" flags="">El-Kébir</w>
  <w f="63" flags="">Elgar</w>
  <w f="63" flags="">Emmanuel-Philibert</w>
  <w f="63" flags="">Erasmus</w>
@@ -47645,7 +47622,6 @@
  <w f="63" flags="">déterrer</w>
  <w f="63" flags="">efficiente</w>
  <w f="63" flags="">effroi</w>
- <w f="63" flags="">el-Kébir</w>
  <w f="63" flags="">embarcadère</w>
  <w f="63" flags="">embarquement</w>
  <w f="63" flags="">embusqués</w>
@@ -50498,7 +50474,6 @@
  <w f="62" flags="">pointures</w>
  <w f="62" flags="">politicienne</w>
  <w f="62" flags="">polyarthrite</w>
- <w f="62" flags="">polynomiales</w>
  <w f="62" flags="">polythéiste</w>
  <w f="62" flags="">ponctue</w>
  <w f="62" flags="">pondu</w>
@@ -52102,7 +52077,6 @@
  <w f="61" flags="">fécondée</w>
  <w f="61" flags="">fétichistes</w>
  <w f="61" flags="">fêta</w>
- <w f="61" flags="">galle</w>
  <w f="61" flags="">gallons</w>
  <w f="61" flags="">gamelan</w>
  <w f="61" flags="">gantois</w>
@@ -52406,7 +52380,6 @@
  <w f="61" flags="">lycanthropes</w>
  <w f="61" flags="">lymphe</w>
  <w f="61" flags="">lyrics</w>
- <w f="61" flags="">länder</w>
  <w f="61" flags="">m'appelle</w>
  <w f="61" flags="">madriers</w>
  <w f="61" flags="">mafieuses</w>
@@ -52462,7 +52435,6 @@
  <w f="61" flags="">modifiables</w>
  <w f="61" flags="">monade</w>
  <w f="61" flags="">monophysisme</w>
- <w f="61" flags="">mons</w>
  <w f="61" flags="">montgolfières</w>
  <w f="61" flags="">montreront</w>
  <w f="61" flags="">monégasques</w>
@@ -53890,7 +53862,6 @@
  <w f="60" flags="">couteuse</w>
  <w f="60" flags="">craignit</w>
  <w f="60" flags="">cramoisi</w>
- <w f="60" flags="">crane</w>
  <w f="60" flags="">cravates</w>
  <w f="60" flags="">cristallisée</w>
  <w f="60" flags="">crochu</w>
@@ -54259,7 +54230,6 @@
  <w f="60" flags="">gazettes</w>
  <w f="60" flags="">gaziers</w>
  <w f="60" flags="">gazéification</w>
- <w f="60" flags="">gaëlique</w>
  <w f="60" flags="">geai</w>
  <w f="60" flags="">gestions</w>
  <w f="60" flags="">glissée</w>
@@ -54422,7 +54392,6 @@
  <w f="60" flags="">l'Argens</w>
  <w f="60" flags="">l'Audiencia</w>
  <w f="60" flags="">l'Aéro-Club</w>
- <w f="60" flags="">l'Eden</w>
  <w f="60" flags="">l'Est-Anglie</w>
  <w f="60" flags="">l'Huveaune</w>
  <w f="60" flags="">l'Ibar</w>
@@ -54448,7 +54417,6 @@
  <w f="60" flags="">l'apposition</w>
  <w f="60" flags="">l'aristocrate</w>
  <w f="60" flags="">l'arrangeur</w>
- <w f="60" flags="">l'artefact</w>
  <w f="60" flags="">l'assignation</w>
  <w f="60" flags="">l'associer</w>
  <w f="60" flags="">l'attaquent</w>
@@ -54902,6 +54870,7 @@
  <w f="60" flags="">rustre</w>
  <w f="60" flags="">râpé</w>
  <w f="60" flags="">réaffirmée</w>
+ <w f="60" flags="">réapparaitre</w>
  <w f="60" flags="">rébus</w>
  <w f="60" flags="">réceptionner</w>
  <w f="60" flags="">réceptionniste</w>
@@ -56571,7 +56540,6 @@
  <w f="59" flags="">guinées</w>
  <w f="59" flags="">gustative</w>
  <w f="59" flags="">guyanaise</w>
- <w f="59" flags="">guérillero</w>
  <w f="59" flags="">gélatineuse</w>
  <w f="59" flags="">génocidaire</w>
  <w f="59" flags="">généra</w>
@@ -56739,7 +56707,6 @@
  <w f="59" flags="abbreviation">l'Ems</w>
  <w f="59" flags="">l'Erie</w>
  <w f="59" flags="">l'Espagnole</w>
- <w f="59" flags="">l'Esterel</w>
  <w f="59" flags="">l'Estrémadure</w>
  <w f="59" flags="abbreviation">l'HMS</w>
  <w f="59" flags="abbreviation">l'ICC</w>
@@ -56853,7 +56820,6 @@
  <w f="59" flags="">laminoirs</w>
  <w f="59" flags="">lasso</w>
  <w f="59" flags="">latentes</w>
- <w f="59" flags="">laure</w>
  <w f="59" flags="">leishmaniose</w>
  <w f="59" flags="">lemmings</w>
  <w f="59" flags="">lenticulaire</w>
@@ -57083,7 +57049,6 @@
  <w f="59" flags="">pathologiste</w>
  <w f="59" flags="">pattern</w>
  <w f="59" flags="">pectoraux</w>
- <w f="59" flags="">pedigree</w>
  <w f="59" flags="">pendage</w>
  <w f="59" flags="">pensez</w>
  <w f="59" flags="">perfectif</w>
@@ -57296,7 +57261,6 @@
  <w f="59" flags="">rotin</w>
  <w f="59" flags="">rouage</w>
  <w f="59" flags="">rougir</w>
- <w f="59" flags="">râga</w>
  <w f="59" flags="">râteau</w>
  <w f="59" flags="">règnera</w>
  <w f="59" flags="">récollets</w>
@@ -57476,7 +57440,6 @@
  <w f="59" flags="">survive</w>
  <w f="59" flags="">surélever</w>
  <w f="59" flags="">suspicieux</w>
- <w f="59" flags="">sutras</w>
  <w f="59" flags="">suève</w>
  <w f="59" flags="">swaps</w>
  <w f="59" flags="">sycomore</w>
@@ -58677,7 +58640,6 @@
  <w f="58" flags="">d'antiquité</w>
  <w f="58" flags="">d'appendices</w>
  <w f="58" flags="">d'arrivées</w>
- <w f="58" flags="">d'artefacts</w>
  <w f="58" flags="">d'artisan</w>
  <w f="58" flags="">d'arête</w>
  <w f="58" flags="">d'assauts</w>
@@ -59844,7 +59806,6 @@
  <w f="58" flags="">savate</w>
  <w f="58" flags="">scalde</w>
  <w f="58" flags="">scandaleuses</w>
- <w f="58" flags="">scenarii</w>
  <w f="58" flags="">schwa</w>
  <w f="58" flags="">scolastiques</w>
  <w f="58" flags="">scripte</w>
@@ -61680,7 +61641,6 @@
  <w f="57" flags="">l'avertir</w>
  <w f="57" flags="">l'aéroclub</w>
  <w f="57" flags="">l'effectivité</w>
- <w f="57" flags="">l'electro</w>
  <w f="57" flags="">l'ellipsoïde</w>
  <w f="57" flags="">l'en-but</w>
  <w f="57" flags="">l'encéphale</w>
@@ -61831,7 +61791,6 @@
  <w f="57" flags="">multifonctions</w>
  <w f="57" flags="">multilatérale</w>
  <w f="57" flags="">multilatérales</w>
- <w f="57" flags="">multimedia</w>
  <w f="57" flags="">multiplexes</w>
  <w f="57" flags="">multipolaire</w>
  <w f="57" flags="">muons</w>
@@ -62271,7 +62230,6 @@
  <w f="57" flags="">savoisienne</w>
  <w f="57" flags="">saxo</w>
  <w f="57" flags="">scellement</w>
- <w f="57" flags="">scenario</w>
  <w f="57" flags="">schizophrènes</w>
  <w f="57" flags="">scintillement</w>
  <w f="57" flags="">scié</w>
@@ -63875,7 +63833,6 @@
  <w f="56" flags="">efficience</w>
  <w f="56" flags="">efficient</w>
  <w f="56" flags="">el-Cheikh</w>
- <w f="56" flags="">el-Kebir</w>
  <w f="56" flags="">embaucha</w>
  <w f="56" flags="">embusqué</w>
  <w f="56" flags="">emmenèrent</w>
@@ -64412,7 +64369,6 @@
  <w f="56" flags="">mentorat</w>
  <w f="56" flags="">menues</w>
  <w f="56" flags="">mercantiliste</w>
- <w f="56" flags="">meta</w>
  <w f="56" flags="">mi-pente</w>
  <w f="56" flags="">microbiologiste</w>
  <w f="56" flags="">micrométéorites</w>
@@ -65477,7 +65433,6 @@
  <w f="55" flags="abbreviation">HBC</w>
  <w f="55" flags="abbreviation">HII</w>
  <w f="55" flags="abbreviation">HP-UX</w>
- <w f="55" flags="abbreviation">HTA</w>
  <w f="55" flags="">Haden</w>
  <w f="55" flags="">Hainan</w>
  <w f="55" flags="">Hallstatt</w>
@@ -66416,7 +66371,6 @@
  <w f="55" flags="">d'Alta</w>
  <w f="55" flags="">d'Aman</w>
  <w f="55" flags="">d'Anagni</w>
- <w f="55" flags="">d'Angoulème</w>
  <w f="55" flags="">d'Anhalt-Dessau</w>
  <w f="55" flags="">d'Anticosti</w>
  <w f="55" flags="">d'Antigua</w>
@@ -66587,7 +66541,6 @@
  <w f="55" flags="">denticules</w>
  <w f="55" flags="">dessécher</w>
  <w f="55" flags="">destitua</w>
- <w f="55" flags="">devanagari</w>
  <w f="55" flags="">diabolo</w>
  <w f="55" flags="">dialoguent</w>
  <w f="55" flags="">diastolique</w>
@@ -66599,7 +66552,6 @@
  <w f="55" flags="">digipack</w>
  <w f="55" flags="">dilapide</w>
  <w f="55" flags="">diluant</w>
- <w f="55" flags="">dime</w>
  <w f="55" flags="">diptère</w>
  <w f="55" flags="">directivité</w>
  <w f="55" flags="">disculpé</w>
@@ -66838,7 +66790,6 @@
  <w f="55" flags="">flavescence</w>
  <w f="55" flags="">fleurettiste</w>
  <w f="55" flags="">flexionnelle</w>
- <w f="55" flags="">florès</w>
  <w f="55" flags="">fluo</w>
  <w f="55" flags="">fléchi</w>
  <w f="55" flags="">fondirent</w>
@@ -67156,7 +67107,6 @@
  <w f="55" flags="">l'ainée</w>
  <w f="55" flags="">l'ajournement</w>
  <w f="55" flags="">l'allocution</w>
- <w f="55" flags="">l'ambigüité</w>
  <w f="55" flags="">l'ambitieuse</w>
  <w f="55" flags="">l'angine</w>
  <w f="55" flags="">l'antifascisme</w>
@@ -67694,6 +67644,7 @@
  <w f="55" flags="">qu'Eugène</w>
  <w f="55" flags="">qu'Henry</w>
  <w f="55" flags="">qu'Ibn</w>
+ <w f="55" flags="">qu'apparait</w>
  <w f="55" flags="">qu'association</w>
  <w f="55" flags="">qu'enfant</w>
  <w f="55" flags="">qu'entraîneur-joueur</w>
@@ -69943,7 +69894,6 @@
  <w f="54" flags="">mennonite</w>
  <w f="54" flags="">mentent</w>
  <w f="54" flags="">mercy</w>
- <w f="54" flags="">mesa</w>
  <w f="54" flags="">meseta</w>
  <w f="54" flags="">mesurera</w>
  <w f="54" flags="">meublées</w>
@@ -70487,7 +70437,6 @@
  <w f="54" flags="">survola</w>
  <w f="54" flags="">suscitaient</w>
  <w f="54" flags="">susvisé</w>
- <w f="54" flags="">sutra</w>
  <w f="54" flags="">synchronique</w>
  <w f="54" flags="">synchronisme</w>
  <w f="54" flags="">syncopé</w>
@@ -72014,7 +71963,6 @@
  <w f="53" flags="">d'Ayen</w>
  <w f="53" flags="">d'Eberhard</w>
  <w f="53" flags="">d'Echéry</w>
- <w f="53" flags="">d'Ecouen</w>
  <w f="53" flags="">d'Efteling</w>
  <w f="53" flags="">d'Eichmann</w>
  <w f="53" flags="">d'Elisa</w>
@@ -73120,7 +73068,6 @@
  <w f="53" flags="">parpaings</w>
  <w f="53" flags="">partiale</w>
  <w f="53" flags="">partirait</w>
- <w f="53" flags="">paseo</w>
  <w f="53" flags="">passacaille</w>
  <w f="53" flags="">pataphysique</w>
  <w f="53" flags="">patibulaire</w>
@@ -74939,6 +74886,7 @@
  <w f="52" flags="">congeler</w>
  <w f="52" flags="">congélateurs</w>
  <w f="52" flags="">conseillera</w>
+ <w f="52">conseillerais</w>
  <w f="52" flags="">conseillères</w>
  <w f="52" flags="">consolidations</w>
  <w f="52" flags="">consoude</w>
@@ -75209,7 +75157,6 @@
  <w f="52" flags="">divergeant</w>
  <w f="52" flags="">divisera</w>
  <w f="52" flags="">doline</w>
- <w f="52" flags="">dona</w>
  <w f="52" flags="">donnât</w>
  <w f="52" flags="">dope</w>
  <w f="52" flags="">dormeurs</w>
@@ -75428,7 +75375,6 @@
  <w f="52" flags="">félibre</w>
  <w f="52" flags="">férue</w>
  <w f="52" flags="">fût-elle</w>
- <w f="52" flags="">fœhn</w>
  <w f="52" flags="">gaité</w>
  <w f="52" flags="">gallicans</w>
  <w f="52" flags="">galope</w>
@@ -77912,10 +77858,8 @@
  <w f="51" flags="">gaspillé</w>
  <w f="51" flags="">gauchisme</w>
  <w f="51" flags="">gaves</w>
- <w f="51" flags="">genera</w>
  <w f="51" flags="">genette</w>
  <w f="51" flags="">gente</w>
- <w f="51" flags="">gentile</w>
  <w f="51" flags="">gentium</w>
  <w f="51" flags="">gibbons</w>
  <w f="51" flags="">gicleur</w>
@@ -80527,7 +80471,6 @@
  <w f="50" flags="">liner</w>
  <w f="50" flags="">lingue</w>
  <w f="50" flags="">linnéen</w>
- <w f="50" flags="">linoleum</w>
  <w f="50" flags="">linoléum</w>
  <w f="50" flags="">linéarisation</w>
  <w f="50" flags="">lipase</w>
@@ -80564,7 +80507,6 @@
  <w f="50" flags="">magnétisation</w>
  <w f="50" flags="">magnéto</w>
  <w f="50" flags="">magnétohydrodynamique</w>
- <w f="50" flags="">mahârâja</w>
  <w f="50" flags="">majorer</w>
  <w f="50" flags="">majorettes</w>
  <w f="50" flags="">makhzen</w>
@@ -83070,7 +83012,6 @@
  <w f="49" flags="">l'Ambigu</w>
  <w f="49" flags="">l'Astra</w>
  <w f="49" flags="">l'Ecclésia</w>
- <w f="49" flags="">l'Estérel</w>
  <w f="49" flags="">l'IDH</w>
  <w f="49" flags="abbreviation">l'ISA</w>
  <w f="49" flags="abbreviation">l'InVS</w>
@@ -83417,7 +83358,6 @@
  <w f="49" flags="">octosyllabiques</w>
  <w f="49" flags="">offensés</w>
  <w f="49" flags="">oisiveté</w>
- <w f="49" flags="">omega</w>
  <w f="49" flags="">omoplate</w>
  <w f="49" flags="">oncogène</w>
  <w f="49" flags="">oncologie</w>
@@ -85347,7 +85287,6 @@
  <w f="48" flags="">césarisme</w>
  <w f="48" flags="">césures</w>
  <w f="48" flags="">côtoiera</w>
- <w f="48" flags="">d'Ares</w>
  <w f="48" flags="">d'Axa</w>
  <w f="48" flags="">d'Hemingway</w>
  <w f="48" flags="abbreviation">d'URL</w>
@@ -85768,7 +85707,6 @@
  <w f="48" flags="">gaucherie</w>
  <w f="48" flags="">gelant</w>
  <w f="48" flags="">gendarmeries</w>
- <w f="48" flags="">gene</w>
  <w f="48" flags="">genin</w>
  <w f="48" flags="">genouillères</w>
  <w f="48" flags="">gentianes</w>
@@ -85806,7 +85744,6 @@
  <w f="48" flags="">gueuse</w>
  <w f="48" flags="">guinée</w>
  <w f="48" flags="">gujarati</w>
- <w f="48" flags="">gurû</w>
  <w f="48" flags="">guéries</w>
  <w f="48" flags="">guérira</w>
  <w f="48" flags="">guérisse</w>
@@ -86135,7 +86072,6 @@
  <w f="48" flags="">lamentant</w>
  <w f="48" flags="">lamenter</w>
  <w f="48" flags="">laminée</w>
- <w f="48" flags="">lander</w>
  <w f="48" flags="">lands</w>
  <w f="48" flags="">langoureux</w>
  <w f="48" flags="">laotiennes</w>
@@ -86293,7 +86229,6 @@
  <w f="48" flags="">mésosphère</w>
  <w f="48" flags="">métalangage</w>
  <w f="48" flags="">mît</w>
- <w f="48" flags="">môns</w>
  <w f="48" flags="">n'aboutiront</w>
  <w f="48" flags="">n'accorda</w>
  <w f="48" flags="">n'apprit</w>
@@ -87166,7 +87101,6 @@
  <w f="47" flags="">Avellino</w>
  <w f="47" flags="">Avesnes</w>
  <w f="47" flags="">Ayutthaya</w>
- <w f="47" flags="abbreviation">BOF</w>
  <w f="47" flags="">Babin</w>
  <w f="47" flags="">Bagotville</w>
  <w f="47" flags="">Bainville</w>
@@ -87876,6 +87810,7 @@
  <w f="47" flags="">blitzkrieg</w>
  <w f="47" flags="">boards</w>
  <w f="47" flags="">boas</w>
+ <w f="47" flags="abbreviation">bof</w>
  <w f="47" flags="">bomba</w>
  <w f="47" flags="">bomber</w>
  <w f="47" flags="">bombés</w>
@@ -87988,7 +87923,6 @@
  <w f="47" flags="">clinicienne</w>
  <w f="47" flags="">cloisonnements</w>
  <w f="47" flags="">closerie</w>
- <w f="47" flags="">clot</w>
  <w f="47" flags="">cloîtrées</w>
  <w f="47" flags="">clématite</w>
  <w f="47" flags="">clôturera</w>
@@ -88967,7 +88901,6 @@
  <w f="47" flags="">pesanteurs</w>
  <w f="47" flags="">petit-duc</w>
  <w f="47" flags="">peupla</w>
- <w f="47" flags="">peña</w>
  <w f="47" flags="">phalangiste</w>
  <w f="47" flags="">pharmacocinétique</w>
  <w f="47" flags="">phasmes</w>
@@ -91145,7 +91078,6 @@
  <w f="46" flags="">impudique</w>
  <w f="46" flags="">impulsa</w>
  <w f="46" flags="">impulsifs</w>
- <w f="46" flags="">imâm</w>
  <w f="46" flags="abbreviation">ina</w>
  <w f="46" flags="">inapplicables</w>
  <w f="46" flags="">incandescents</w>
@@ -91300,7 +91232,6 @@
  <w f="46" flags="">l'ex-directeur</w>
  <w f="46" flags="">l'ex-épouse</w>
  <w f="46" flags="">l'examine</w>
- <w f="46" flags="">l'exigüité</w>
  <w f="46" flags="">l'expatriation</w>
  <w f="46" flags="">l'expliquent</w>
  <w f="46" flags="">l'exploratrice</w>
@@ -91441,13 +91372,11 @@
  <w f="46" flags="">martyriser</w>
  <w f="46" flags="">masseuse</w>
  <w f="46" flags="">mastectomie</w>
- <w f="46" flags="">mega</w>
  <w f="46" flags="">membrée</w>
  <w f="46" flags="">mentant</w>
  <w f="46" flags="">mentionnèrent</w>
  <w f="46" flags="">menuets</w>
  <w f="46" flags="">mer-sol</w>
- <w f="46" flags="">metro</w>
  <w f="46" flags="">mi-championnat</w>
  <w f="46" flags="">micocoulier</w>
  <w f="46" flags="">micro-algues</w>
@@ -93469,7 +93398,6 @@
  <w f="45" flags="">concouraient</w>
  <w f="45" flags="">concourra</w>
  <w f="45" flags="">condensations</w>
- <w f="45" flags="">condottieres</w>
  <w f="45" flags="">confectionna</w>
  <w f="45" flags="">configurées</w>
  <w f="45" flags="">conflagration</w>
@@ -96795,7 +96723,6 @@
  <w f="44" flags="">eschatologie</w>
  <w f="44" flags="">escomptées</w>
  <w f="44" flags="">espar</w>
- <w f="44" flags="">esperanto</w>
  <w f="44" flags="">espionnait</w>
  <w f="44" flags="">esquivant</w>
  <w f="44" flags="">essaimage</w>
@@ -97285,9 +97212,7 @@
  <w f="44" flags="">laryngite</w>
  <w f="44" flags="">laryngé</w>
  <w f="44" flags="">latéralité</w>
- <w f="44" flags="">lauré</w>
  <w f="44" flags="">laze</w>
- <w f="44" flags="">leges</w>
  <w f="44" flags="">lestées</w>
  <w f="44" flags="">lettrages</w>
  <w f="44" flags="">levantine</w>
@@ -97372,7 +97297,6 @@
  <w f="44" flags="">micronoyaux</w>
  <w f="44" flags="">miette</w>
  <w f="44" flags="">militarisés</w>
- <w f="44" flags="">millenium</w>
  <w f="44" flags="">millerandage</w>
  <w f="44" flags="">minant</w>
  <w f="44" flags="">mini-jupe</w>
@@ -99977,7 +99901,6 @@
  <w f="43" flags="">mnémoniques</w>
  <w f="43" flags="">mobilisera</w>
  <w f="43" flags="">modifieront</w>
- <w f="43" flags="">moitie</w>
  <w f="43" flags="">molester</w>
  <w f="43" flags="">mona</w>
  <w f="43" flags="">monistes</w>
@@ -101868,7 +101791,6 @@
  <w f="42" flags="">dichotomies</w>
  <w f="42" flags="">dichotomiques</w>
  <w f="42" flags="">dilapidations</w>
- <w f="42" flags="">dimes</w>
  <w f="42" flags="">diplodocus</w>
  <w f="42" flags="">disait-elle</w>
  <w f="42" flags="">discréditées</w>
@@ -102899,7 +102821,6 @@
  <w f="42" flags="">restituait</w>
  <w f="42" flags="">retracés</w>
  <w f="42" flags="">retranscrivent</w>
- <w f="42" flags="">retro</w>
  <w f="42" flags="">retrouvez</w>
  <w f="42" flags="">reversant</w>
  <w f="42" flags="">revirent</w>
@@ -104901,7 +104822,6 @@
  <w f="41" flags="">garde-temps</w>
  <w f="41" flags="">gardes-pêche</w>
  <w f="41" flags="">gastroentérite</w>
- <w f="41" flags="">gates</w>
  <w f="41" flags="">gaufrier</w>
  <w f="41" flags="">gaules</w>
  <w f="41" flags="">gaussiens</w>
@@ -105532,7 +105452,6 @@
  <w f="41" flags="">plafonnées</w>
  <w f="41" flags="">plaisanté</w>
  <w f="41" flags="">planctons</w>
- <w f="41" flags="">plantagenêt</w>
  <w f="41" flags="">plantera</w>
  <w f="41" flags="">plaqueminier</w>
  <w f="41" flags="">playa</w>
@@ -108603,7 +108522,6 @@
  <w f="40" flags="">radiatives</w>
  <w f="40" flags="">radiophare</w>
  <w f="40" flags="">radiosondes</w>
- <w f="40" flags="">raga</w>
  <w f="40" flags="">rages</w>
  <w f="40" flags="">rainbow</w>
  <w f="40" flags="">rainuré</w>
@@ -108827,7 +108745,6 @@
  <w f="40" flags="">sarclage</w>
  <w f="40" flags="">satori</w>
  <w f="40" flags="">saturations</w>
- <w f="40" flags="">satî</w>
  <w f="40" flags="">saupoudrage</w>
  <w f="40" flags="">saurez</w>
  <w f="40" flags="">sauvez</w>
@@ -111688,7 +111605,6 @@
  <w f="39" flags="">monèmes</w>
  <w f="39" flags="">moralisant</w>
  <w f="39" flags="">moro</w>
- <w f="39" flags="">moré</w>
  <w f="39" flags="">mosaïsme</w>
  <w f="39" flags="">moteur-boîte</w>
  <w f="39" flags="">motivèrent</w>
@@ -111728,6 +111644,7 @@
  <w f="39" flags="">n'adopta</w>
  <w f="39" flags="">n'agissant</w>
  <w f="39" flags="">n'allèrent</w>
+ <w f="39">n'apportez</w>
  <w f="39" flags="">n'approcha</w>
  <w f="39" flags="">n'atteindrait</w>
  <w f="39" flags="">n'empêchaient</w>
@@ -115033,7 +114950,6 @@
  <w f="37" flags="">croyait-on</w>
  <w f="37" flags="">cryptogrammes</w>
  <w f="37" flags="">créancière</w>
- <w f="37" flags="">crémerie</w>
  <w f="37" flags="">crénelages</w>
  <w f="37" flags="">crépue</w>
  <w f="37" flags="">crétacées</w>
@@ -115728,7 +115644,6 @@
  <w f="37" flags="">harkas</w>
  <w f="37" flags="">harnachements</w>
  <w f="37" flags="">hast</w>
- <w f="37" flags="">haste</w>
  <w f="37" flags="">hellénisants</w>
  <w f="37" flags="">hennin</w>
  <w f="37" flags="">herbagers</w>
@@ -118031,7 +117946,6 @@
  <w f="36" flags="">doutons</w>
  <w f="36" flags="">doyennes</w>
  <w f="36" flags="">drives</w>
- <w f="36" flags="">drivé</w>
  <w f="36" flags="">droguées</w>
  <w f="36" flags="">droitières</w>
  <w f="36" flags="">ductus</w>
@@ -119687,6 +119601,7 @@
  <w f="35" flags="">appelleraient</w>
  <w f="35" flags="">appoggiatures</w>
  <w f="35" flags="">appointée</w>
+ <w f="35">apporteriez</w>
  <w f="35" flags="">apposèrent</w>
  <w f="35" flags="">apprendraient</w>
  <w f="35" flags="">approprie</w>
@@ -120848,7 +120763,6 @@
  <w f="35" flags="">fantasmatiques</w>
  <w f="35" flags="">fardage</w>
  <w f="35" flags="">faro</w>
- <w f="35" flags="">fasciculés</w>
  <w f="35" flags="">fascinaient</w>
  <w f="35" flags="">fascisation</w>
  <w f="35" flags="">fayard</w>
@@ -121985,7 +121899,6 @@
  <w f="35" flags="">pastore</w>
  <w f="35" flags="">pataude</w>
  <w f="35" flags="">patauge</w>
- <w f="35" flags="">pati</w>
  <w f="35" flags="">paturon</w>
  <w f="35" flags="">paturons</w>
  <w f="35" flags="">patènes</w>
@@ -123976,7 +123889,6 @@
  <w f="34" flags="">déviateur</w>
  <w f="34" flags="">dîna</w>
  <w f="34" flags="">ectopiques</w>
- <w f="34" flags="">eden</w>
  <w f="34" flags="">effectueraient</w>
  <w f="34" flags="">effraies</w>
  <w f="34" flags="">effritée</w>
@@ -124531,7 +124443,6 @@
  <w f="34" flags="">mestres</w>
  <w f="34" flags="">mesureront</w>
  <w f="34" flags="">meublent</w>
- <w f="34" flags="">mi-aout</w>
  <w f="34" flags="">mi-humaines</w>
  <w f="34" flags="">mi-voix</w>
  <w f="34" flags="">micelle</w>
@@ -127052,7 +126963,6 @@
  <w f="33" flags="">pavanes</w>
  <w f="33" flags="">pavant</w>
  <w f="33" flags="">pavimenteux</w>
- <w f="33" flags="">penelope</w>
  <w f="33" flags="">pensionna</w>
  <w f="33" flags="">pentacles</w>
  <w f="33" flags="">perborate</w>
@@ -131024,7 +130934,6 @@
  <w f="31" flags="">châtelaines</w>
  <w f="31" flags="">chènevières</w>
  <w f="31" flags="">cicatrisante</w>
- <w f="31" flags="">cicéro</w>
  <w f="31" flags="">cicéronienne</w>
  <w f="31" flags="">cimentant</w>
  <w f="31" flags="">cincles</w>
@@ -131800,7 +131709,6 @@
  <w f="31" flags="">grattés</w>
  <w f="31" flags="">gravissaient</w>
  <w f="31" flags="">gravois</w>
- <w f="31" flags="">greco</w>
  <w f="31" flags="">grecs-orthodoxes</w>
  <w f="31" flags="">greffera</w>
  <w f="31" flags="">grenadines</w>
@@ -131965,7 +131873,6 @@
  <w f="31" flags="">ivresses</w>
  <w f="31" flags="">j'écoutais</w>
  <w f="31" flags="">jaillie</w>
- <w f="31" flags="">jaina</w>
  <w f="31" flags="">jamaïquaines</w>
  <w f="31" flags="">janus</w>
  <w f="31" flags="">javelles</w>
@@ -132169,7 +132076,6 @@
  <w f="31" flags="">lattée</w>
  <w f="31" flags="">laudatives</w>
  <w f="31" flags="">lavandins</w>
- <w f="31" flags="">leger</w>
  <w f="31" flags="">levantines</w>
  <w f="31" flags="">lexicologiques</w>
  <w f="31" flags="">libéralisa</w>
@@ -132223,7 +132129,6 @@
  <w f="31" flags="">macro-algues</w>
  <w f="31" flags="">macrocéphale</w>
  <w f="31" flags="">macèrent</w>
- <w f="31" flags="">maelstrom</w>
  <w f="31" flags="">magnésiennes</w>
  <w f="31" flags="">magnétisées</w>
  <w f="31" flags="">mahométan</w>
@@ -134732,7 +134637,6 @@
  <w f="30" flags="">farcit</w>
  <w f="30" flags="">fardé</w>
  <w f="30" flags="">fasciation</w>
- <w f="30" flags="">fasciculé</w>
  <w f="30" flags="">fascinations</w>
  <w f="30" flags="">faucha</w>
  <w f="30" flags="">fausse-renoncule</w>
@@ -136328,6 +136232,8 @@
  <w f="30" flags="">sérails</w>
  <w f="30" flags="">sérialisée</w>
  <w f="30" flags="">séricigènes</w>
+ <w f="30">t'adresser</w>
+ <w f="30">t'adresses</w>
  <w f="30" flags="">t'aider</w>
  <w f="30" flags="">t'emmerde</w>
  <w f="30" flags="">taboues</w>
@@ -137547,7 +137453,6 @@
  <w f="28" flags="">d'arrangeurs</w>
  <w f="28" flags="">d'arrhes</w>
  <w f="28" flags="">d'arrière-plans</w>
- <w f="28" flags="">d'artefact</w>
  <w f="28" flags="">d'arythmies</w>
  <w f="28" flags="">d'assurance-crédit</w>
  <w f="28" flags="">d'astigmatisme</w>
@@ -138268,7 +138173,6 @@
  <w f="28" flags="">herbager</w>
  <w f="28" flags="">herborisa</w>
  <w f="28" flags="">herculéen</w>
- <w f="28" flags="">herpes</w>
  <w f="28" flags="">hiatale</w>
  <w f="28" flags="">histidines</w>
  <w f="28" flags="">hivernages</w>
@@ -146791,11 +146695,9 @@
  <w f="25" flags="">fédé</w>
  <w f="25" flags="">fédéral-provincial</w>
  <w f="25" flags="">félicitaient</w>
- <w f="25" flags="">féra</w>
  <w f="25" flags="">gagnais</w>
  <w f="25" flags="">gaillets</w>
  <w f="25" flags="">gainiers</w>
- <w f="25" flags="">gallé</w>
  <w f="25" flags="">galonnés</w>
  <w f="25" flags="">galoubet-tambourin</w>
  <w f="25" flags="">galoubets</w>
@@ -147598,7 +147500,6 @@
  <w f="25" flags="">maçonnes</w>
  <w f="25" flags="">maïzena</w>
  <w f="25" flags="">melba</w>
- <w f="25" flags="">melissa</w>
  <w f="25" flags="">menteuses</w>
  <w f="25" flags="">mentholée</w>
  <w f="25" flags="">mentionnerons</w>
@@ -147712,7 +147613,6 @@
  <w f="25" flags="">mouvaient</w>
  <w f="25" flags="">moyen-bavarois</w>
  <w f="25" flags="">moyen-néerlandais</w>
- <w f="25" flags="">moëres</w>
  <w f="25" flags="">mugir</w>
  <w f="25" flags="">multivariées</w>
  <w f="25" flags="">musé</w>
@@ -151397,7 +151297,6 @@
  <w f="23" flags="">dandiner</w>
  <w f="23" flags="">dansais</w>
  <w f="23" flags="">danse-contact</w>
- <w f="23" flags="">daphne</w>
  <w f="23" flags="">dardes</w>
  <w f="23" flags="">daring</w>
  <w f="23" flags="">dariques</w>
@@ -152474,7 +152373,6 @@
  <w f="23" flags="">kantiens</w>
  <w f="23" flags="">keno</w>
  <w f="23" flags="">khamsin</w>
- <w f="23" flags="">khân</w>
  <w f="23" flags="">kiki</w>
  <w f="23" flags="">kilkenny</w>
  <w f="23" flags="">kinder</w>
@@ -152886,7 +152784,6 @@
  <w f="23" flags="">lacèrent</w>
  <w f="23" flags="">lacée</w>
  <w f="23" flags="">lae</w>
- <w f="23" flags="">laiche</w>
  <w f="23" flags="">laideron</w>
  <w f="23" flags="">laisse-toi</w>
  <w f="23" flags="">laisseras</w>
@@ -153811,7 +153708,6 @@
  <w f="23" flags="">poissonnières</w>
  <w f="23" flags="">poissé</w>
  <w f="23" flags="">polacre</w>
- <w f="23" flags="">polaroid</w>
  <w f="23" flags="">polatouches</w>
  <w f="23" flags="">polissons</w>
  <w f="23" flags="">pollupostage</w>
@@ -154711,7 +154607,6 @@
  <w f="23" flags="">servocommande</w>
  <w f="23" flags="">servomécanismes</w>
  <w f="23" flags="">sexagésimaux</w>
- <w f="23" flags="">shâh</w>
  <w f="23" flags="">siccatifs</w>
  <w f="23" flags="">sifflaient</w>
  <w f="23" flags="">sillages</w>
@@ -155963,6 +155858,7 @@
  <w f="21" flags="">Motte-Saint-Valentin</w>
  <w f="21" flags="">Moulin-Brûlé</w>
  <w f="21" flags="">Musser</w>
+ <w f="21" flags="">Mélissa</w>
  <w f="21" flags="">Métro-Richelieu</w>
  <w f="21" flags="">Mézières-en-Gâtinais</w>
  <w f="21" flags="">Napoléon-Charles</w>
@@ -158839,7 +158735,6 @@
  <w f="21" flags="">hee</w>
  <w f="21" flags="">heller</w>
  <w f="21" flags="">hellénismes</w>
- <w f="21" flags="">herbés</w>
  <w f="21" flags="">herve</w>
  <w f="21" flags="">heurtons</w>
  <w f="21" flags="">hiberné</w>
@@ -159635,7 +159530,6 @@
  <w f="21" flags="">lactifères</w>
  <w f="21" flags="">lacéra</w>
  <w f="21" flags="">laguerre</w>
- <w f="21" flags="">laiches</w>
  <w f="21" flags="">laisserais</w>
  <w f="21" flags="">lamentos</w>
  <w f="21" flags="">lamentèrent</w>
@@ -160062,7 +159956,6 @@
  <w f="21" flags="">méga-corporation</w>
  <w f="21" flags="">mélamine-formaldéhyde</w>
  <w f="21" flags="">mélangeront</w>
- <w f="21" flags="">mélissa</w>
  <w f="21" flags="">mémorisait</w>
  <w f="21" flags="">ménologes</w>
  <w f="21" flags="">ménopausique</w>
@@ -160666,7 +160559,6 @@
  <w f="21" flags="">peinard</w>
  <w f="21" flags="">peinez</w>
  <w f="21" flags="">peinturer</w>
- <w f="21" flags="">pelagos</w>
  <w f="21" flags="">pelliculée</w>
  <w f="21" flags="">peltaste</w>
  <w f="21" flags="">pelté</w>
@@ -165431,7 +165323,6 @@
  <w f="18" flags="">crédit-carbone</w>
  <w f="18" flags="">créditera</w>
  <w f="18" flags="">crédulités</w>
- <w f="18" flags="">crémeries</w>
  <w f="18" flags="">crénelées-dentelées</w>
  <w f="18" flags="">créolisés</w>
  <w f="18" flags="">créosotes</w>
@@ -170056,7 +169947,6 @@
  <w f="18" flags="">position-impulsion</w>
  <w f="18" flags="">postulations</w>
  <w f="18" flags="">posât</w>
- <w f="18" flags="">potencé</w>
  <w f="18" flags="">potentialisé</w>
  <w f="18" flags="">potenza</w>
  <w f="18" flags="">potestative</w>
@@ -172484,7 +172374,6 @@
  <w f="18" flags="">écartes</w>
  <w f="18" flags="">échafaudant</w>
  <w f="18" flags="">échafaudèrent</w>
- <w f="18" flags="">échancre</w>
  <w f="18" flags="">échangeons</w>
  <w f="18" flags="">échangeraient</w>
  <w f="18" flags="">écharper</w>
@@ -172751,7 +172640,6 @@
  <w f="15" flags="">Antoinette-Élisabeth</w>
  <w f="15" flags="">Anvers-Bruxelles</w>
  <w f="15" flags="">Anvers-Wavre</w>
- <w f="15" flags="">Apportez-moi</w>
  <w f="15" flags="">Arbre-Saint-Pierre</w>
  <w f="15" flags="">Ardenne-Rives-de-Meuse</w>
  <w f="15" flags="">Argas</w>
@@ -173065,6 +172953,7 @@
  <w f="15" flags="">Château-Voué</w>
  <w f="15" flags="">Château-sur-Aisne</w>
  <w f="15" flags="">Chérasse</w>
+ <w f="15" flags="">Cicero</w>
  <w f="15" flags="">Cinq-Chemins</w>
  <w f="15" flags="">Cinq-Moulins</w>
  <w f="15" flags="">Cinq-Provinces</w>
@@ -174677,6 +174566,7 @@
  <w f="15" flags="">apporte-t-il</w>
  <w f="15" flags="">apporterez</w>
  <w f="15" flags="">apportes</w>
+ <w f="15" flags="">apportez-moi</w>
  <w f="15" flags="">apprend-t-on</w>
  <w f="15" flags="">apprenti-dessinateur</w>
  <w f="15" flags="">apprenti-pâtissier</w>
@@ -175926,8 +175816,6 @@
  <w f="15" flags="">ciboriums</w>
  <w f="15" flags="">cicatrisations</w>
  <w f="15" flags="">cicatrisés</w>
- <w f="15" flags="">cicero</w>
- <w f="15" flags="">cicéros</w>
  <w f="15" flags="">ciel-terre</w>
  <w f="15" flags="">cillées</w>
  <w f="15" flags="">cimentera</w>
@@ -179207,7 +179095,6 @@
  <w f="15" flags="">gemmologiste</w>
  <w f="15" flags="">gentillets</w>
  <w f="15" flags="">gentillettes</w>
- <w f="15" flags="">genépi</w>
  <w f="15" flags="">gercées</w>
  <w f="15" flags="">germanisa</w>
  <w f="15" flags="">germinaux</w>
@@ -179448,7 +179335,6 @@
  <w f="15" flags="">heng</w>
  <w f="15" flags="">hennissant</w>
  <w f="15" flags="">heptagones</w>
- <w f="15" flags="">herbé</w>
  <w f="15" flags="">herméticité</w>
  <w f="15" flags="">herri</w>
  <w f="15" flags="">hersages</w>
@@ -180957,7 +180843,6 @@
  <w f="15" flags="">limitez</w>
  <w f="15" flags="">limonites</w>
  <w f="15" flags="">limée</w>
- <w f="15" flags="">limón</w>
  <w f="15" flags="">lingotières</w>
  <w f="15" flags="">liniers</w>
  <w f="15" flags="">linotypie</w>
@@ -182796,7 +182681,6 @@
  <w f="15" flags="">passage-clef</w>
  <w f="15" flags="">passagers-kilomètres</w>
  <w f="15" flags="">passassent</w>
- <w f="15" flags="">passat</w>
  <w f="15" flags="">passe-plats</w>
  <w f="15" flags="">passe-rose</w>
  <w f="15" flags="">passementière</w>
@@ -182844,7 +182728,6 @@
  <w f="15" flags="">pelas</w>
  <w f="15" flags="">pelliculées</w>
  <w f="15" flags="">pelotonnée</w>
- <w f="15" flags="">peléen</w>
  <w f="15" flags="">peléennes</w>
  <w f="15" flags="">penchât</w>
  <w f="15" flags="">pense-il</w>
@@ -182868,7 +182751,6 @@
  <w f="15" flags="">perdit-il</w>
  <w f="15" flags="">perdureraient</w>
  <w f="15" flags="">perdîmes</w>
- <w f="15" flags="">peres</w>
  <w f="15" flags="">perfectionneront</w>
  <w f="15" flags="">perfoliées</w>
  <w f="15" flags="">perforera</w>
@@ -183005,7 +182887,6 @@
  <w f="15" flags="">planchera</w>
  <w f="15" flags="">planchéiée</w>
  <w f="15" flags="">planeuse</w>
- <w f="15" flags="">plantagenet</w>
  <w f="15" flags="">planteraient</w>
  <w f="15" flags="">planteuses</w>
  <w f="15" flags="">plastiqueurs</w>
@@ -187747,7 +187628,6 @@
  <w f="10" flags="">côtoyez</w>
  <w f="10" flags="">d'Agnat</w>
  <w f="10" flags="">d'Albert-le-Grand</w>
- <w f="10" flags="">d'Ales</w>
  <w f="10" flags="">d'Algérien</w>
  <w f="10" flags="">d'Angoumois-infanterie</w>
  <w f="10" flags="">d'Anonyme</w>
@@ -188046,7 +187926,6 @@
  <w f="10" flags="">ferryboat</w>
  <w f="10" flags="">feule</w>
  <w f="10" flags="">fichier-clef</w>
- <w f="10" flags="">fieffe</w>
  <w f="10" flags="">fieffer</w>
  <w f="10" flags="">fies</w>
  <w f="10" flags="">fieu</w>
@@ -188231,7 +188110,6 @@
  <w f="10" flags="">hava</w>
  <w f="10" flags="">havir</w>
  <w f="10" flags="">hebdomadiers</w>
- <w f="10" flags="">hela</w>
  <w f="10" flags="">helminthe</w>
  <w f="10" flags="">henni</w>
  <w f="10" flags="">herzégovine</w>
@@ -188729,7 +188607,6 @@
  <w f="10" flags="">malpolis</w>
  <w f="10" flags="">malta</w>
  <w f="10" flags="">malter</w>
- <w f="10" flags="">malé</w>
  <w f="10" flags="">mancha</w>
  <w f="10" flags="">mangano</w>
  <w f="10" flags="">mante-religieuse</w>
@@ -189012,7 +188889,6 @@
  <w f="10" flags="">pastelle</w>
  <w f="10" flags="">pasteurienne</w>
  <w f="10" flags="">pastillas</w>
- <w f="10" flags="">paséo</w>
  <w f="10" flags="">patachons</w>
  <w f="10" flags="">patay</w>
  <w f="10" flags="">patoche</w>
@@ -191229,7 +191105,6 @@
  <w f="1" flags="">miton</w>
  <w f="1" flags="">moblots</w>
  <w f="1" flags="">moch</w>
- <w f="1" flags="">moeres</w>
  <w f="1" flags="">moha</w>
  <w f="1" flags="">moisant</w>
  <w f="1" flags="">moise</w>
@@ -191271,7 +191146,6 @@
  <w f="1" flags="">mémère</w>
  <w f="1" flags="">ménine</w>
  <w f="1" flags="">ményanthe</w>
- <w f="1" flags="">mésa</w>
  <w f="1" flags="">métra</w>
  <w f="1" flags="">métromanie</w>
  <w f="1" flags="">mézeray</w>
@@ -191837,6 +191711,7 @@
  <w f="0" flags="e">gouine</w>
  <w f="0" flags="n">gousse</w>
  <w f="0" flags="n">gémissement</w>
+ <w f="0">haha</w>
  <w f="0" flags="n">hardcore</w>
  <w f="0" flags="n">hermaphrodite</w>
  <w f="0" flags="e">homo</w>
diff --git a/java/proguard.flags b/java/proguard.flags
index 752ced3e379026c69c168c875ebffd6f50b98faa..ca205b927948997126492ee12b2fba27bea627c0 100644
--- a/java/proguard.flags
+++ b/java/proguard.flags
@@ -3,10 +3,6 @@
   <init>(...);
 }
 
--keep class com.android.inputmethod.latin.Flag {
-  *;
-}
-
 -keep class com.android.inputmethod.keyboard.ProximityInfo {
   <init>(com.android.inputmethod.keyboard.ProximityInfo);
 }
diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict
index 98a9361b586582d61e3446e509023902a15bb340..e02e300e4c0a69e2c670be0ee4c3a2336288c97c 100644
Binary files a/java/res/raw/main_en.dict and b/java/res/raw/main_en.dict differ
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
index 717078c93031f228fabbefb1da4166970eadeb1c..8e616591c15d0962ac6ce15e8f024aa90022a2b2 100644
Binary files a/java/res/raw/main_fr.dict and b/java/res/raw/main_fr.dict differ
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 22543efe5aabb39ad7d24699269e8da61e6ff7df..2738328133f703138d62b0bf32b356d153b92c1f 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Verstek"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Stel kontakname voor"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gebruik name van kontakte vir voorstelle en korreksies"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Aktiveer herkorrigerings"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Stel voorstelle vir herkorrigerings"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Outohoofletters"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Voeg woordeboeke by"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Hoofwoordeboek"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Matig"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressief"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Baie aggressief"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Volgendewoordvoorstelle"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gebruik vorige woord om voorstelle te verbeter"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Volgendewoordvoorspelling"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gebruik vorige woord ook vir voorspelling"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Volgende woordvoorstelle"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Gebaseer op vorige woord"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Gestoor"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Gaan"</string>
     <string name="label_next_key" msgid="362972844525672568">"Volgende"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index a1b168cb7ad314466c8a4c4eeb429479d6b11cfc..a6373ccb6a36d0e2a66e259c3d9041d79df80cb4 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ነባሪ"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"የዕውቂያ ስም ጠቁም"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"ከዕውቂያዎች ለጥቆማዎች እና ማስተካከያዎች ስሞች ተጠቀም"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"ድጋሚ ለማስተካከል አንቃ"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"ድጋሚ ለማስተካከል ጥቆማዎችን አዘጋጅ"</string>
     <string name="auto_cap" msgid="1719746674854628252">"ራስ-ሰር አቢይ ማድረግ"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"መዝገበ ቃላቶች ጨምር"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"ዋና መዝገበ ቃላት"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"መጠነኛ"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"ኃይለኛ"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"በጣም ቁጡ"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"የቀጣይ ቃል አስተያየቶች"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ምክሮችን ለማሻሻል ቀዳሚ ቃል ተጠቀም"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"የቀጣይ ቃል ግምት"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"ለትንበያ የቀደመ ቃል እንዲሁ ተጠቀም"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"የቀጣይ ቃል አስተያየቶች"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"በቀዳሚው ቃል ላይ የተመሠረተ"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ተቀምጧል"</string>
     <string name="label_go_key" msgid="1635148082137219148">"ሂድ"</string>
     <string name="label_next_key" msgid="362972844525672568">"በመቀጠል"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 2a220744737ff3a716e4528beb9acd68924c3e3a..9e6f1ea5130c6d3b7f47f9e9707afb35b0932a36 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"افتراضي"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"اقتراح أسماء جهات الاتصال"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"استخدام الأسماء من جهات الاتصال للاقتراحات والتصحيحات"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"تمكين عمليات إعادة التصحيح"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"تعيين اقتراحات لعمليات إعادة التصحيح"</string>
     <string name="auto_cap" msgid="1719746674854628252">"أحرف كبيرة تلقائيًا"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"القواميس الإضافية"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"القاموس الرئيسي"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"معتدل"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"حاد"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"شديد الصرامة"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"اقتراحات الكلمات التالية"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"استخدام الكلمة السابقة لتحسين الاقتراحات"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"تنبؤ الكلمات التالية"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"استخدام الكلمة السابقة أيضًا للتنبؤ"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"اقتراحات الكلمات التالية"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"استنادًا إلى الكلمة السابقة"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : تم الحفظ"</string>
     <string name="label_go_key" msgid="1635148082137219148">"تنفيذ"</string>
     <string name="label_next_key" msgid="362972844525672568">"التالي"</string>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index ff3213ad609b8884731e6c9f103cfcbabf919f77..fb371f4c3d5068bb2436266e46412652f2c2b618 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Па змаўчанні"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Прапан. імёны кантактаў"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Выкарыстоўваць імёны са спісу кантактаў для прапаноў і выпраўл."</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Уключыць карэкцiроўкі"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Задаць прапановы для карэкцiроўкі"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Аўтаматычна рабіць вялікія літары"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Дадатковыя слоўнікі"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Асноўны слоўнік"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Сціплы"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Агрэсіўны"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Вельмі агрэсіўны"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Падказкi для наступнага слова"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Выкарыстаць папярэдняе слова, каб палепшыць прапановы"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Падказка наступнага слова"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Выкарыстанне папярэдняга слова для падказак"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Падказкi для наступнага слова"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"На аснове папярэдняга слова"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Захаваныя"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Пачаць"</string>
     <string name="label_next_key" msgid="362972844525672568">"Далей"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 5e916cef08d2384ddbcba3c9eeab2d6ad925edc8..94945c03bdfc2a65895f5ac2231ee35adc0a6ad2 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"По подразбиране"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Предложения за контакти"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Използване на имена от „Контакти“ за предложения и поправки"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Повторни поправки: Актив."</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Задаване на предложения за повторни поправки"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Автоматично поставяне на главни букви"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Добавени речници"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Основен речник"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Умерено"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Агресивно"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Много агресивно"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Предложения за следващата дума"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Използване на предишната дума за подобряване на предложенията"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Предвиждане на следващата дума"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Използване на предишната дума и за предвиждане"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Предложения за следващата дума"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Въз основа на предишната дума"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Запазено"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Старт"</string>
     <string name="label_next_key" msgid="362972844525672568">"Напред"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 1b7cfc255ed259a7ff74cbb6ab5f70c31ac13d06..b6fb56093f59598243deea37ea07c2a565879de7 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminat"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Suggereix noms contactes"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilitza els noms de Contactes per a suggeriments i correccions"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Activa la capacitat de tornar a corregir"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Estableix suggeriments per tornar a corregir"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Majúscules automàtiques"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionaris complementaris"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Diccionari principal"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderada"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Molt agressiu"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Suggeriments de paraula següent"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilitza la paraula anterior per millorar els suggeriments"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Predicció de paraula següent"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilitza també la paraula anterior per a la predicció"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Suggeriments de paraula següent"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"En funció de la paraula anterior"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: desada"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Vés"</string>
     <string name="label_next_key" msgid="362972844525672568">"Següent"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 7e6ee0b4a797a8ba3c44f6de44ad2ae16943eadc..5818d5c6fa0089e9087d4aa8f6e80e8a72c64b15 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Výchozí"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Navrhovat jména kontaktů"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Použít jména ze seznamu kontaktů k návrhům a opravám"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Povolit opětovné opravy"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastavit návrhy pro opětovné opravy"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Velká písmena automaticky"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Doplňkové slovníky"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Hlavní slovník"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mírné"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivní"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Velmi agresivní"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Návrh dalšího slova"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Použít předchozí slovo ke zlepšení návrhů"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Odhad dalšího slova"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Použít předchozí slovo také pro odhad"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Návrhy dalšího slova"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Na základě předchozího slova"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Uloženo"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Přejít"</string>
     <string name="label_next_key" msgid="362972844525672568">"Další"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index c6800a95290df1f07f8a8ba204b675496e44f18d..dc1df0772a6c82ee01e035e7d109fba7c9292b06 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Foreslå navne på kontakter"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Brug navne fra Kontaktpersoner til forslag og rettelser"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Aktivér fornyet rettelse"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Angiv forslag til fornyet rettelse"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Skriv aut. med stort"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Tillægsordbøger"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Hovedordbog"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderat"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressiv"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Meget aggressiv"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Forslag til næste ord"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Brug forrige ord til at forbedre forslag"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Forudsigelse af næste ord"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Brug også tidligere ord til forudsigelse"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Forslag til næste ord"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Baseret på tidligere ord"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Gemt"</string>
     <string name="label_go_key" msgid="1635148082137219148">"GÃ¥"</string>
     <string name="label_next_key" msgid="362972844525672568">"Næste"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index cd2d78e4af6701c1f6edf5817601cc9c2a35cb0c..b2495253496885360dafe55cd1fe9c49ba391164 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Kontakte vorschlagen"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen aus \"Kontakte\" als Vorschläge und Korrekturmöglichkeiten anzeigen"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Korrekturen aktivieren"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Vorschläge für Korrekturen festlegen"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Autom. Groß-/Kleinschr."</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Erweiterte Wörterbücher"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Allgemeines Wörterbuch"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mäßig"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Stark"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sehr stark"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Vorschläge für nächstes Wort"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Zur Verbesserung von Vorschlägen vorheriges Wort verwenden"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Vervollständigung für nächstes Wort"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Vorheriges Wort auch für Vervollständigung verwenden"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Vorschläge für nächstes Wort"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Auf Grundlage des vorherigen Wortes"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: gespeichert"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Los"</string>
     <string name="label_next_key" msgid="362972844525672568">"Weiter"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 5dcbf43baea6a8dec920c3a64228ba612606ee9e..d9e1aa8c4a883e7bd2de085d16160da5dc9cb9de 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Προεπιλογή"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Πρόταση ονομάτων επαφών"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Χρησιμοποιήστε ονόματα από τις Επαφές για προτάσεις και διορθ."</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Ενεργ. επανάλ. διορθώσεων"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ορισμός προτάσεων για επαναλήψεις διορθώσεων"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Αυτόματη χρήση κεφαλαίων"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Πρόσθετα λεξικά"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Κύριο λεξικό"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Μέτρια"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Υψηλή"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Πολύ επιθετική"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Προτάσεις επόμενων λέξεων"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Χρήση προηγούμενης λέξης για τη βελτίωση προτάσεων"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Πρόβλεψη επόμενης λέξης"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Χρησιμοποιήστε, επίσης, την προηγούμενη λέξη για πρόβλεψη"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Προτάσεις επόμενων λέξεων"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Βάσει προηγούμενης λέξης"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Αποθηκεύτηκε"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Μετ."</string>
     <string name="label_next_key" msgid="362972844525672568">"Επόμενο"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index cd9b218e79865c81157ad34f2ebbabf73b76c1d5..7241e5df0c2da06bcc37d6249a877278acbcfc84 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Suggest Contact names"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Use names from Contacts for suggestions and corrections"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Enable recorrections"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Set suggestions for recorrections"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Auto-capitalisation"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Add-on dictionaries"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Main dictionary"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressive"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Very aggressive"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Next word suggestions"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Use previous word to improve suggestion"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Next word prediction"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Use previous word also for prediction"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Next word suggestions"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Based on previous word"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Saved"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Go"</string>
     <string name="label_next_key" msgid="362972844525672568">"Next"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 39ca40903d228979e799ef4b8b52a7b3ca0954ce..01d9912da72727c5c661e8e988baf10062550150 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminada"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nombres de contacto"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nombres de los contactos para sugerencias y correcciones"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Activar correcciones"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para realizar correcciones"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresivo"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerencias para la palabra siguiente"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar la palabra anterior para mejorar las sugerencias"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Predicción de la palabra siguiente"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Usar la palabra anterior también para predicción."</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Sugerencias de palabra siguiente"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Según la palabra anterior"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
     <string name="label_next_key" msgid="362972844525672568">"Siguiente"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 79a36cccd7eee6762f2dcbe83e26bd7736866026..f97d93ddf56f07e90f176c715e23e01d61cbb616 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir contactos"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nombres de contactos para sugerencias y correcciones"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Activar nuevas correcciones"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para nuevas correcciones"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Parcial"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresiva"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerir siguiente palabra"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palabra anterior para mejorar las sugerencias"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Predecir siguiente palabra"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilizar también la palabra anterior para realizar la predicción"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Sugerir siguiente palabra"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Según la palabra anterior"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
     <string name="label_next_key" msgid="362972844525672568">"Sig."</string>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index 45870d3a942aaa20685ead23cc30ad75994077d7..e4f0f2f58e062fd8fe58df6e14a97bb80a1c530f 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Vaikeseade"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Soovita kontaktkirjeid"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Kasuta soovitusteks ja parandusteks nimesid kontaktiloendist"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Uute paranduste lubamine"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Soovituste seadmine uute paranduste jaoks"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Automaatne suurtähtede kasutamine"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Pistiksõnaraamatud"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Peamine sõnaraamat"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mõõdukas"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressiivne"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Väga agressiivne"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Järgmise sõna soovitused"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Kasuta soovituste täiustamiseks eelmist sõna"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Järgmise sõna ennustus"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Kasuta ennustuseks ka eelmist sõna"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Järgmise sõna soovitused"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Eelmise sõna põhjal"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : salvestatud"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Mine"</string>
     <string name="label_next_key" msgid="362972844525672568">"Edasi"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 9f0e5aaa4458b5eb8122d46aea5cb033b037f4cd..4ad5025eb1849fe559768caa8c4c4dd97015124e 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"پیش فرض"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"پیشنهاد نام های مخاطب"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"برای پیشنهاد و تصحیح از نام مخاطبین استفاده شود"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"فعال کردن تصحیح مجدد"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"تنظیم پیشنهادات برای تصحیح مجدد"</string>
     <string name="auto_cap" msgid="1719746674854628252">"نوشتن با حروف بزرگ خودکار"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"فرهنگ‌های لغت افزودنی"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"فرهنگ‌ لغت اصلی"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"متوسط"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"فعال"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"بسیار پرخاشگرانه"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"پیشنهادات کلمه بعدی"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"برای بهبود پیشنهاد از کلمه قبلی استفاده شود"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"پیش‌بینی کلمه بعدی"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"استفاده از کلمه قبلی برای پیش بینی"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"پیشنهادات کلمه بعدی"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"بر اساس کلمه قبلی"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ذخیره شد"</string>
     <string name="label_go_key" msgid="1635148082137219148">"برو"</string>
     <string name="label_next_key" msgid="362972844525672568">"بعدی"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index f4dff35b90525be8f73056fbb9c3bfc1bac67a8b..3ca48be5d60d016e7ed1bf2cfbb79d951cf642a6 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Oletus"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Ehdota yhteystietojen nimiä"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Käytä yhteystietojen nimiä ehdotuksissa ja korjauksissa"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Ota korjaukset käyttöön"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Aseta korjausehdotuksia"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Automaattiset isot kirjaimet"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Lisäsanakirjat"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Pääsanakirja"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Osittainen"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Täysi"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Hyvin aggressiivinen"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Seuraavan sanan ehdotukset"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Paranna ehdotuksia aiempien sanojen avulla"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Seuraavan sanan ennakointi"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Käytä edellistä sanaa myös ennakointiin"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Seuraavan sanan ehdotukset"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Perustuu edelliseen sanan"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Tallennettu"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Siirry"</string>
     <string name="label_next_key" msgid="362972844525672568">"Seur."</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 1094c4ac3041073aa8b2e2720a1869aabf8dd6fc..e457480c1914783faf12bd5fbb503687b525cc8c 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Proposer noms de contacts"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utiliser des noms de contacts pour les suggestions et corrections"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Activer la recorrection"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Définir des suggestions de recorrection"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Majuscules auto"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dictionnaires complémentaires"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Dictionnaire principal"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Simple"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Proactive"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Très exigeante"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Suggestions pour le mot suivant"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Améliorer les suggestions grâce au mot précédent"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Prédiction du mot suivant"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utiliser le mot précédent pour la prédiction"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Suggestions pour le mot suivant"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Suggestions basées sur le mot précédent"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : enregistré"</string>
     <string name="label_go_key" msgid="1635148082137219148">"OK"</string>
     <string name="label_next_key" msgid="362972844525672568">"Suiv."</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index c131e127849b2ca9260502aa1e34197dc8566031..0b76cfde6a90406866dd422d00d9a6208f12025f 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"डिफ़ॉल्ट"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"संपर्क नाम सुझाएं"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"सुझाव और सुधार के लिए संपर्क से नामों का उपयोग करें"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"पुन: सुधार सक्षम करें"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"पुन: सुधार के लि‍ए सुझाव सेट करें"</string>
     <string name="auto_cap" msgid="1719746674854628252">"स्‍वत: अक्षर बड़े करना"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"एड-ऑन डिक्शनरी"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"मुख्‍य डिक्‍शनरी"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"साधारण"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"तीव्र"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"बहुत तीव्र"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"अगला शब्‍द सुझाव"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"सुझावों को बेहतर बनाने के लिए पिछले शब्‍द का उपयोग करें"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"अगला शब्‍द पूर्वानुमान"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"पूर्वानुमान के लिए पिछले शब्द का उपयोग करें"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"अगले शब्द सुझाव"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"पिछले शब्दों के आधार पर"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: सहेजा गया"</string>
     <string name="label_go_key" msgid="1635148082137219148">"जाएं"</string>
     <string name="label_next_key" msgid="362972844525672568">"अगला"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index f8a198df267982dbf262fd7d2397b42b3e371fdc..c8649e95177df9d5a34af6603ed5bb808ff906fb 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Zadano"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Predlaži imena kontakata"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Upotreba imena iz Kontakata za prijedloge i ispravke"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Omogući ponovne ispravke"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Postavite prijedloge za ponovne ispravke"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Automatsko pisanje velikih slova"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Rječnici-dodaci"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Glavni rječnik"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Skromno"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivno"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Vrlo agresivno"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Prijedlozi za sljedeću riječ"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Upotrijebi prethodnu riječ radi poboljšanja prijedloga"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Predviđanje sljedeće riječi"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Upotrijebite prethodnu riječ i za predviđanje"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Prijedlozi za sljedeću riječ"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Na temelju prethodne riječi"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Spremljeno"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Idi"</string>
     <string name="label_next_key" msgid="362972844525672568">"Dalje"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index fc1ac12278ddec415ec00de6bb5dbdd33ac68737..d2a38cb2441e585bdf2f737ee0698c8166056ffa 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Alapbeállítás"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Javasolt névjegyek"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"A névjegyek használata a javaslatokhoz és javításokhoz"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Újbóli javítás engedélyezése"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Javaslatok beállítása az újbóli javításokhoz"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Automatikusan nagy kezdőbetű"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Bővítmények: szótárak"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Fő szótár"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mérsékelt"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresszív"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Nagyon agresszív"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Következő szóra vonatkozó javaslatok"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Javaslatok fejlesztése az előző szó használatával"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Következő szó előrejelzése"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Az előző szó használata a prediktív bevitelhez is"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Következő szóra vonatkozó javaslatok"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Az előző szó alapján"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : mentve"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Ugrás"</string>
     <string name="label_next_key" msgid="362972844525672568">"Tovább"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index a7a2c038345a891ad98a031ee2ec68ef9476012d..2d10e627445f1c1aec082444f1ed046e9f2f22f8 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kontak"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kontak untuk saran dan koreksi"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Aktifkan koreksi ulang"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setel saran untuk koreksi ulang"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Kapitalisasi otomatis"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Kamus pengaya"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Sederhana"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sangat agresif"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Saran kata berikutnya"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gunakan kata sebelumnya untuk meningkatkan saran"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Prediksi kata berikutnya"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gunakan kata sebelumnya juga untuk prediksi"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Saran kata berikutnya"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Berdasarkan kata sebelumnya"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Telah disimpan"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Buka"</string>
     <string name="label_next_key" msgid="362972844525672568">"Berikutnya"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index e77a0d04d1e73cbfd46d06f27ec2a11e6e3daeff..c3a2b5135adea35d4b653bab6714d3743970c495 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinito"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Suggerisci nomi di contatti"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizza nomi di Contatti per suggerimenti e correzioni"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Attiva nuove correzioni"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Imposta suggerimenti per nuove correzioni"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Maiuscole automatiche"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dizionari aggiuntivi"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Dizionario principale"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Media"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Massima"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Massima"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Suggerimenti parola successiva"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usa parola precedente per migliorare suggerimenti"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Previsione parola successiva"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Usa anche la parola precedente per la previsione"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Suggerimenti parola successiva"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"In base alla parola precedente"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : parola salvata"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Vai"</string>
     <string name="label_next_key" msgid="362972844525672568">"Avanti"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 000c9f337315007381c4a2fe2d2e8ecdbfd2791e..3859993f9238c1c8e9330214f59eb5c6cbf4012d 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ברירת מחדל"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"הצע שמות של אנשי קשר"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"השתמש בשמות מרשימת אנשי הקשר עבור הצעות ותיקונים"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"הפוך תיקונים חוזרים לפעילים"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"הגדר הצעות עבור תיקונים חוזרים"</string>
     <string name="auto_cap" msgid="1719746674854628252">"הפיכת אותיות לרישיות באופן אוטומטי"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"הוספת מילונים"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"מילון ראשי"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"מצומצם"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"מחמיר"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"מחמיר מאוד"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"הצעות המילה הבאה"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"השתמש במילה הקודמת כדי לשפר את ההצעות"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"חיזוי המילה הבאה"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"השתמש במילה הקודמת גם עבור חיזוי"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"הצעות המילה הבאה"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"בהתבסס על המילה הקודמת"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : נשמרה"</string>
     <string name="label_go_key" msgid="1635148082137219148">"בצע"</string>
     <string name="label_next_key" msgid="362972844525672568">"הבא"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 05dd3a3641791af05386951dcc2dbdccfcd2c563..f9349f5409d3ca24c853ba6846ccf08fa96f6586 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"デフォルト"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"候補の連絡先名を表示"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"連絡先の名前を使用して候補表示や自動修正を行います"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"再修正を有効にする"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"再修正の候補を挿入する"</string>
     <string name="auto_cap" msgid="1719746674854628252">"自動大文字変換"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"アドオン辞書"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"メイン辞書"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"中"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"å¼·"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"最も強い"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"次の入力候補"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"直前の単語から入力候補を予測します"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"次の入力候補を予測"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"前の語句も予測に使用"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"次の入力候補"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"前の語句に基づいた入力候補表示"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:保存しました"</string>
     <string name="label_go_key" msgid="1635148082137219148">"実行"</string>
     <string name="label_next_key" msgid="362972844525672568">"次へ"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 6a998838a2051babd6c85a989f38b5d042947f30..cd8cb6b5194b13052d9a4eb061e2b04834cb54d5 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"기본값"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"주소록 이름 활용"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"추천 및 수정에 주소록의 이름 사용"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"재수정 가능 설정"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"재수정 추천어 사전 활성화"</string>
     <string name="auto_cap" msgid="1719746674854628252">"자동 대문자화"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"사전 추가"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"기본 사전"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"약"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"중"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"ê°•"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"다음 추천 검색어"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"이전 단어를 사용하여 추천 검색어 개선"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"다음 예상 검색어"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"이전 단어를 사용하여 예상 검색어 표시"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"다음 검색어 추천"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"이전 단어에 기반한 추천"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: 저장됨"</string>
     <string name="label_go_key" msgid="1635148082137219148">"이동"</string>
     <string name="label_next_key" msgid="362972844525672568">"다음"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 86bfc371491b81e65abc2dbcb5dcc488945a499a..2f6abc85679bbccaaeefc53a80174079c79af54b 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Numatytasis"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Siūlyti kontaktų vardus"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Siūlant ir taisant naudoti vardus iš „Kontaktų“"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Įdiegti pakartotinius pataisymus"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nustatyti pakartotinio pataisymo pasiūlymus"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Automatinis didžiųjų raidžių rašymas"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Papildomi žodynai"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Pagrindinis žodynas"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Vidutinis"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Atkaklus"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Labai agresyviai"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Kito žodžio pasiūlymai"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Naudoti ankstesnį žodį pasiūlymams patobulinti"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Kito žodžio numatymas"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Numatant naudoti ir ankstesnį žodį"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Kito žodžio pasiūlymai"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Pagal ankstesnį žodį"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: išsaugota"</string>
     <string name="label_go_key" msgid="1635148082137219148">"PradÄ—ti"</string>
     <string name="label_next_key" msgid="362972844525672568">"Kitas"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 403e0f2d17b32b1425296ac848253815eb118d80..66dd1473e9db0b1df4036ce4be6457499c88dea4 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Noklusējums"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Ieteikt kontaktp. vārdus"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Izmantot kontaktpersonu vārdus kā ieteikumus un labojumus"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Iespējot atk. labojumus"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Iestatīt atkārtotu labojumu ieteikumus"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Automātiska lielo burtu lietošana"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Papildinājumu vārdnīcas"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Galvenā vārdnīca"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"MÄ“rena"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresīva"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Ļoti radikāla"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Nākamā vārda ieteikumi"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Ieteikumu uzlabošanai izmantot iepriekšējo vārdu"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Nākamā vārda prognozēšana"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Izmantot iepriekšējo vārdu arī prognozēm"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Nākamie vārdu ieteikumi"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Pamatojoties uz iepriekšējo vārdu"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: saglabāts"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Sākt"</string>
     <string name="label_next_key" msgid="362972844525672568">"Tālāk"</string>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index 60f5a4133edd579379abcdfccaa4d943e6348824..53c902039051a332f08649804eb1b3157eb9a6ac 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Lalai"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Cadangkan nama Kenalan"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama daripada Kenalan untuk cadangan dan pembetulan"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Dayakan pembetulan semula"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Tetapkan cadangan untuk pembetulan semula"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Huruf besar auto"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Kamus tambahan"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Sederhana"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sangat agresif"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Cadangan perkataan seterusnya"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gunakan perkataan sebelumnya untuk memperbaik cadangan"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Ramalan perkataan seterusnya"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gunakan juga perkataan sebelumnya untuk ramalan"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Cadangan perkataan seterusnya"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Berdasarkan perkataan sebelumnya"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Disimpan"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Pergi"</string>
     <string name="label_next_key" msgid="362972844525672568">"Seterusnya"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index fc2bd5539b99edf09397aa882f43712c6f45c80a..bdde36ae85346a822144761841587c3d38b1313e 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Foreslå kontaktnavn"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Bruk navn fra Kontakter til forslag og korrigeringer"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Aktiver korrigeringer"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Angi forslag for korrigeringer"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Stor forbokstav"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Tilleggsordbøker"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Hovedordliste"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderat"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Omfattende"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Veldig aggressiv"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Forslag til rettelser av neste ord"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Bruk forrige ord til å forbedre forslagene"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Forslag til neste ord"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Bruk forrige ord også for forslag"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Forslag til neste ord"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Basert på det forrige ordet"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Lagret"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Utfør"</string>
     <string name="label_next_key" msgid="362972844525672568">"Neste"</string>
@@ -146,7 +142,7 @@
     <string name="enable" msgid="5031294444630523247">"Aktiver"</string>
     <string name="not_now" msgid="6172462888202790482">"Ikke nå"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Inndatastilen finnes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Nyttighetsmodus"</string>
+    <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Bruksstudiemodus"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Innstillinger for vibrasjonsvarighet ved tastetrykk"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Innstillinger for lydstyrke ved tastetrykk"</string>
 </resources>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 26d5e3f20a1c5dc445a107f57236fa51e9b6b651..9624e176e7c964bb2d82c1b72916a8b7c3318b32 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standaard"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Contactnamen suggereren"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen uit Contacten gebruiken voor suggesties en correcties"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Verbeteringen inschakelen"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Suggesties instellen voor verbeteringen"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Auto-hoofdlettergebruik"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Woordenboeken toevoegen"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Algemeen woordenboek"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Normaal"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressief"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Zeer agressief"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Volgende woordsuggesties"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Vorig woord gebruiken om suggesties te verbeteren"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Volgende woordvoorspelling"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Het voorgaande woord ook voor voorspelling gebruiken"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Suggesties voor volgend woord"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Op basis van het vorige woord"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: opgeslagen"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Start"</string>
     <string name="label_next_key" msgid="362972844525672568">"Verder"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index dc4f396a79f1f6dd669e08600f9018e81301c507..c8a72b77a740fd0cf4c25480de9a246b28b4fd2e 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Wartość domyślna"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Proponuj osoby z kontaktów"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"W propozycjach i poprawkach użyj nazwisk z kontaktów"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"WÅ‚Ä…cz poprawki"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ustaw sugestie poprawek"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Wstawiaj wielkie litery"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dodatkowe słowniki"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Słownik główny"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Umiarkowana"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresywna"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Bardzo agresywna"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestie kolejnych słów"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Używaj poprzedniego wyrazu, by polepszyć sugestie"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Przewidywanie następnego wyrazu"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Przewiduj również na podstawie poprzedniego słowa"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Sugestie kolejnych słów"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Na podstawie poprzedniego słowa"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Zapisano"</string>
     <string name="label_go_key" msgid="1635148082137219148">"OK"</string>
     <string name="label_next_key" msgid="362972844525672568">"Dalej"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 35eedd82ae3742bae1c432ee05e4e5ead0e27c40..cef2ce75be10c33ce17e1784d07c5c64856e1318 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinido"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de Contactos"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nomes dos Contactos para sugestões e correções"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Ativar correções"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Definir sugestões para correções"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Letras maiúsculas automáticas"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dicionários extras"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Dicionário principal"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderada"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressiva"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muito agressivo"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestões da palavra seguinte"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilizar palavra anterior para melhorar sugestões"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Previsão da palavra seguinte"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilizar a palavra anterior também para predição"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Sugestões da palavra seguinte"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Com base na palavra anterior"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
     <string name="label_go_key" msgid="1635148082137219148">"OK"</string>
     <string name="label_next_key" msgid="362972844525672568">"Avançar"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index a12fc23e1d63b1b2c0ea3aa9c4663ac9863858fd..d092879cf1b7f1db147b992188c35210301cd953 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Padrão"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de contato"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nomes dos Contatos para sugestões e correções"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Ativar recorreções"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Definir sugestões para recorreções"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Capitaliz. automática"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dicionários complementares"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Dicionário principal"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressivo"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muito agressivo"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestões p/ palavra seguinte"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palavra anterior para melhorar as sugestões"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Previsão da palavra seguinte"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Use também a palavra anterior para prever"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Sugestões para a palavra seguinte"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Com base na palavra anterior"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Salvo"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
     <string name="label_next_key" msgid="362972844525672568">"Avançar"</string>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index c6c936e4929b296888adc93a8c4dd78de4d6a4a9..b39691ceb9dfce6e72bfa0a525d587faa487655a 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -67,10 +67,6 @@
     <skip />
     <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
     <skip />
-    <!-- no translation found for enable_span_insert (7204653105667167620) -->
-    <skip />
-    <!-- no translation found for enable_span_insert_summary (2947317657871394467) -->
-    <skip />
     <string name="auto_cap" msgid="1719746674854628252">"Maiusclas automaticas"</string>
     <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
     <skip />
@@ -98,13 +94,9 @@
     <skip />
     <!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
     <skip />
-    <!-- no translation found for bigram_suggestion (8169311444438922902) -->
-    <skip />
-    <!-- no translation found for bigram_suggestion_summary (6635527607242625713) -->
-    <skip />
-    <!-- no translation found for bigram_prediction (3216364899483135294) -->
+    <!-- no translation found for bigram_prediction (5809665643352206540) -->
     <skip />
-    <!-- no translation found for bigram_prediction_summary (1747261921174300098) -->
+    <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
     <skip />
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Memorisà"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Dai"</string>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 523a855c74b827e0764b2eb727877690349fb7cb..08275665cd32c44770ca4f5adfe2c504207899cf 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Prestabilit"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sugeraţi nume din Agendă"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizaţi numele din Agendă pentru sugestii şi corecţii"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Activaţi rectificările"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setaţi sugestii pentru rectificări"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Auto-capitalizare"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dicţionare suplimentare"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Dicţionar principal"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderată"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivă"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Foarte exigentă"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestii pentru cuvântul următor"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilizaţi cuvântul anterior pentru a îmbunătăţi sugestiile"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Predicţia cuvântului următor"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Se utilizează şi cuvântul precedent pentru predicţii"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Sugestii pentru cuvântul următor"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Bazate pe cuvântul precedent"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: salvat"</string>
     <string name="label_go_key" msgid="1635148082137219148">"OK"</string>
     <string name="label_next_key" msgid="362972844525672568">"ÃŽnainte"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 34fdb0f5c0b5f7bd2996a778238bc95b422ca1e8..77ffe7b55d64fbaf20cc526c6e49ff296739a036 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -44,10 +44,8 @@
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Задержка закрытия"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без задержки"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"По умолчанию"</string>
-    <string name="use_contacts_dict" msgid="4435317977804180815">"Подсказки имен контактов"</string>
-    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Подсказки и исправления на основе имен из контактов"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Автоисправление"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Показывать варианты исправления"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"Подсказывать имена"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Подсказывать исправления на основе имен из списка контактов"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Заглавные автоматически"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Дополнительные словари"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Основной словарь"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Умеренное"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Активное"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Очень активно"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Следующие варианты"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Использовать предыдущее слово, чтобы исправить предложенные варианты"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Следующая подсказка"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Использовать предыдущее слово для прогнозирования"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Подсказка для следующего слова"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Подсказки, основанные на предыдущих словах"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: сохранено"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Поиск"</string>
     <string name="label_next_key" msgid="362972844525672568">"Далее"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 41fc0cf242e339a76deef82ceef6296f697a4af6..2b31bd85884b2c8ae4c589d53a57a824a36d26f7 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predvolená"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Navrhnúť mená kontaktov"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Používať mená z Kontaktov na návrhy a opravy"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Povoliť opätovné opravy"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastaviť návrhy pre opätovné opravy"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Veľké písmená automaticky"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Doplnkové slovníky"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Hlavný slovník"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mierne"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresívne"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Veľmi agresívne"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Návrhy ďalšieho slova"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Na zlepšenie návrhov použiť predchádzajúce slovo"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Odhad ďalšieho slova"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Použiť predchádzajúce slovo aj pre predpoveď"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Návrhy ďalšieho slova"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Na základe predchádzajúceho slova"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Uložené"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Hľadať"</string>
     <string name="label_next_key" msgid="362972844525672568">"ÄŽalej"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index f18de78bc2dd975013893b87547473ec9b9f42db..05e20b04cb1cdab4b26a55d1093d8bad30bd4345 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Privzeto"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Predlagaj imena stikov"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Uporaba imen iz stikov za predloge in popravke"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Omogoči vnovične popravke"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastavitev predlogov za vnovične popravke"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Samod. velike začetnice"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dodatni slovarji"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Glavni slovar"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Zmerno"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Strogo"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Zelo strogo"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Predlogi naslednje besede"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Predloge izboljšaj s prejšnjo besedo"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Predvidevanje naslednje besede"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Uporabi prejšnjo besedo tudi za predvidevanje"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Predlogi za naslednjo besedo"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Na podlagi prejšnje besede"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: shranjeno"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Pojdi"</string>
     <string name="label_next_key" msgid="362972844525672568">"Naprej"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 11e678ebc2e61ba74d37ad24cec177f7a5c97658..43fe7003d894f70aec201a3188248f35d9cc35e5 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Подразумевано"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Предложи имена контаката"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Користи имена из Контаката за предлоге и исправке"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Омогући поновне исправке"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Подешавање предлога за поновне исправке"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Аутоматски унос великих слова"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Помоћни речници"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Главни речник"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Умерено"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Агресивно"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Веома агресивно"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Предлози за следећу реч"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Користи претходну реч за побољшање предлога"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Предвиђање следеће речи"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Користи претходну реч и за предвиђање"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Предлози за следећу реч"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"На основу претходне речи"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Сачувано"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Иди"</string>
     <string name="label_next_key" msgid="362972844525672568">"Следеће"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index bf1e5054f94bd8a383f1789378ae9dd2c12f2f75..f24446976480eee8105e9fdbd660161d9e084f1b 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Föreslå kontaktnamn"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Använd namn från Kontakter för förslag och korrigeringar"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Aktivera omkorrigeringar"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ställ in förslag för omkorrigeringar"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Automatiska versaler"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Tilläggsordlistor"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Huvudordlistan"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"MÃ¥ttlig"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressiv"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Mycket aggressivt"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Föreslå nästa ord"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Förbättra förslagen med föregående ord"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Förutspå nästa ord"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Använd även föregående ord för att ge förslag"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Föreslå nästa ord"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Baserat på föregående ord"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: sparat"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Kör"</string>
     <string name="label_next_key" msgid="362972844525672568">"Nästa"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index f416fcd76eaef4125da0ec5e02549ed8c674345c..9cec8679d8cc6104865910578e629cad6e005aa7 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Chaguo-msingi"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Pendekeza majini ya Anwani"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Tumia majina kutoka kwa Anwani kwa mapendekezo na marekebisho"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Wezesha masahihisho mapya"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Weka mapendekezo kwa ajili ya kusahihisha upya"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Uwekaji wa herufi kubwa kiotomatiki"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Nyongeza za kamusi"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Kamusi kuu"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Ya wastani"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Ya hima"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Changamfu zaidi"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Mapendekezo ya neno lifuatalo"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Tumia neno la awali ili kuboresha mapendekezo"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Utabiri wa neno lifuatalo"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Tumia  neno la awali pia kwa udadisi"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Mapendekezo ya neno lifuatalo"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Kulingana na neno la awali"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Imehifadhiwa"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Nenda"</string>
     <string name="label_next_key" msgid="362972844525672568">"Ifuatayo"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 6f25a202495d2e348801a1b42e4afa176ca0269b..174ee45070d380ae933fc4d318e8a4e71629b736 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ค่าเริ่มต้น"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"แนะนำชื่อผู้ติดต่อ"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"ใช้ชื่อจากรายชื่อติดต่อสำหรับคำแนะนำและการแก้ไข"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"เปิดใช้งานการแก้ไขซ้ำ"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"ตั้งค่าคำแนะนำสำหรับการแก้ไขซ้ำ"</string>
     <string name="auto_cap" msgid="1719746674854628252">"ปรับเป็นตัวพิมพ์ใหญ่อัตโนมัติ"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"พจนานุกรม Add-On"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"พจนานุกรมหลัก"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ปานกลาง"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"เข้มงวด"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"เข้มงวดมาก"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"คำแนะนำสำหรับคำถัดไป"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ใช้คำก่อนหน้านี้เพื่อปรับปรุงคำแนะนำ"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"การคาดคะเนคำถัดไป"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"ใช้คำก่อนหน้านี้สำหรับการคาดคะเน"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"คำแนะนำสำหรับคำถัดไป"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"ตามคำก่อนหน้า"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : บันทึกแล้ว"</string>
     <string name="label_go_key" msgid="1635148082137219148">"ไป"</string>
     <string name="label_next_key" msgid="362972844525672568">"ถัดไป"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index e2fe6c5b4b3f572c2f358780f4680501ffe07d5c..25801ca7dcf47954de1353c91c3b94fd2a3c7125 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Mungkahi pangalan Contact"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gamitin pangalan mula Mga Contact sa mga mungkahi\'t pagwawasto"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Paganahin ang mga muling pagtatama"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Magtakda ng mga suhestyon para sa mga muling pagtatama"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Auto-capitalization"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Mga diksyunaryo na add-on"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Pangunahing diksyunaryo"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresibo"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Napaka-agresibo"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Mga paghuhula sa susunod na salita"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gamitin ang naunang salita para mapahusay ang mga suhestiyon"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Paghuhula sa susunod na salita"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gamitin ang nakaraang salita para din sa hula"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Mga suhestiyon sa susunod na salita"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Batay sa nakaraang salita"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Na-save"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Punta"</string>
     <string name="label_next_key" msgid="362972844525672568">"Susunod"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 16411b8edf3c5911560243ee15f53d85ddf86a7d..190736e82fcc35300c878aab7e10b405c404380c 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Varsayılan"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Kişi Adları öner"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Öneri ve düzeltmeler için Kişiler\'deki adları kullan"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Düzeltmeleri etkinleştir"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Yeniden düzeltmeler için önerileri ayarla"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak büyük fark yap"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Ek sözlükler"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Ana sözlük"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Ölçülü"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Çok geniş ölçekte"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Sonraki kelime önerileri"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Önerileri geliştirmek için önceki kelimeyi kullan"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Sonraki kelime tahmini"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Önceki kelimeyi de tahmin için kullan"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Sonraki kelime önerileri"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Önceki kelimeye dayanarak"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kaydedildi"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Git"</string>
     <string name="label_next_key" msgid="362972844525672568">"Ä°leri"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index c2e743b45bb2d445cf3f76a11dcfd358ef902783..04a8a638ec84a8aace75b932acc0e319201462fc 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"За умовчанням"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Пропон. імена контактів"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Використ. імена зі списку контактів для пропозицій і виправлень"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Увімкнути виправлення"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Показувати варіанти автовиправлень"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Авто викор. вел. літер"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Додані словники"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Основний словник"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Помірне"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Активне"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Дуже активне"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Пропозиції наступного слова"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Використати попереднє слово для покращення пропозицій"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Передбачення наступного слова"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Використовувати попереднє слово також як передбачений запит"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Пропозиції наступного слова"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"На основі попереднього слова"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : збережено"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Іти"</string>
     <string name="label_next_key" msgid="362972844525672568">"Далі"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 9ce2d5a78d7d12325a6963b9a3c244776a08f123..c9dc0e644de22ec39f8413b9cd02d0e723baaaf7 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Mặc định"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Đề xuất tên liên hệ"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Sử dụng tên từ Danh bạ cho các đề xuất và chỉnh sửa"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Bật sửa đổi lại"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Đặt đề xuất cho các sửa đổi lại"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Tự động viết hoa"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Thêm từ điển"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Từ điển chính"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Đơn giản"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Linh hoạt"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Rất linh hoạt"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Đề xuất từ tiếp theo"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Sử dụng từ trước đó để cải tiến đề xuất"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Dự đoán từ tiếp theo"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Cũng sử dụng từ trước đó để dự đoán"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Đề xuất từ tiếp theo"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Dựa trên từ trước đó"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Đã lưu"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Tìm"</string>
     <string name="label_next_key" msgid="362972844525672568">"Tiếp theo"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 4907f202fdf67f38e6a6cb24cbc2982f33ac1f8e..9f5e4633d4961c16bb89b5d930d5606b74f7d5e3 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"默认"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"联系人姓名建议"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"使用联系人中的姓名提供建议和更正"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"允许再次更正"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"设置建议以用于再次更正"</string>
     <string name="auto_cap" msgid="1719746674854628252">"自动大写"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"附加词典"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"主词典"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"小改"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"大改"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"改动极大"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"下一字词建议"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"使用上一字词改进建议"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"下一字词预测"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"结合前一个字词进行预测"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"下一字词建议"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"根据上一个字词提供建议"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已保存"</string>
     <string name="label_go_key" msgid="1635148082137219148">"开始"</string>
     <string name="label_next_key" msgid="362972844525672568">"下一步"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 9179e669b986ac8cc6e04a3ed0e34ca7501bf7a9..20592dc44ab0adbe89e907a1885ed689891dca2d 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"預設"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"建議聯絡人名稱"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"根據「聯絡人」名稱提供建議與修正"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"啟用重新更正"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"設定建議供重新更正"</string>
     <string name="auto_cap" msgid="1719746674854628252">"自動大寫"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"外掛字典"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"主要字典"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"更正範圍小"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"更正範圍大"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"更正範圍極大"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"下一個字詞建議"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"根據前一個字詞找出更適合的建議"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"下一個字詞預測"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"同樣使用前一個字詞進行預測"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"下一個字詞建議"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"根據先前字詞產生"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已儲存"</string>
     <string name="label_go_key" msgid="1635148082137219148">"開始"</string>
     <string name="label_next_key" msgid="362972844525672568">"繼續"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 3f7c96b66e1a3ce1a7e13affd67ff8241a077b69..35cb99cf8b2e3f01ae939a87237f0b926fc5c143 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -46,8 +46,6 @@
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Okuzenzakalelayo"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sikisela amagama Othintana nabo"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Amagama abasebenzisi kusuka Kothintana nabo bokusikisela nokulungisa"</string>
-    <string name="enable_span_insert" msgid="7204653105667167620">"Vumela ukulungiswa kabusha"</string>
-    <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setha iziphakamiso zokulungisa kabusha"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Ukwenza ofeleba okuzenzakalelayo"</string>
     <string name="configure_dictionaries_title" msgid="4238652338556902049">"Faka izichazamazwi"</string>
     <string name="main_dictionary" msgid="4798763781818361168">"Isichazamazwi sakho ngqangi"</string>
@@ -62,10 +60,8 @@
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Thobekile"</string>
     <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Bukhali"</string>
     <string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Nobudlova kakhulu"</string>
-    <string name="bigram_suggestion" msgid="8169311444438922902">"Iziphakamiso zegama elilandelayo"</string>
-    <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Sebenzisa igama elandulele ukuthuthukisa iziphakamiso"</string>
-    <string name="bigram_prediction" msgid="3216364899483135294">"Ukuqagela kwegama elilandelayo"</string>
-    <string name="bigram_prediction_summary" msgid="1747261921174300098">"Sebenzisa igama langaphambilini ukuze uqagele"</string>
+    <string name="bigram_prediction" msgid="5809665643352206540">"Iziphakamiso zegama elilandelayo"</string>
+    <string name="bigram_prediction_summary" msgid="3253961591626441019">"Ngokususela egameni langaphambilini"</string>
     <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kulondoloziwe"</string>
     <string name="label_go_key" msgid="1635148082137219148">"Iya"</string>
     <string name="label_next_key" msgid="362972844525672568">"Okulandelayo"</string>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index d6a68d0dc499b4f6b804b14b125542d399a434d7..0970aeee03960ff943f5de0847d8b9df1192f919 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -181,6 +181,52 @@
     <!-- Description for Bulgarian (BDS) subtype. -->
     <string name="subtype_bulgarian_bds">%s (BDS)</string>
 
+    <!-- Compatibility map from subtypeLocale:subtypeExtraValue to keyboardLayoutSet -->
+    <string-array name="locale_and_extra_value_to_keyboard_layout_set_map">
+        <item>en_US:TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwerty</item>
+        <item>en_GB:TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwerty</item>
+        <item>ar:SupportTouchPositionCorrection</item>
+        <item>arabic</item>
+        <item>cs:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwertz</item>
+        <item>da:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>nordic</item>
+        <item>de:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwertz</item>
+        <item>es:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>spanish</item>
+        <item>fi:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>nordic</item>
+        <item>fr:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>azerty</item>
+        <item>fr_CA:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwerty</item>
+        <item>hr:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwertz</item>
+        <item>hu:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwertz</item>
+        <item>it:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwerty</item>
+        <item>iw:SupportTouchPositionCorrection</item>
+        <item>hebrew</item>
+        <item>nb:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>nordic</item>
+        <item>nl:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwerty</item>
+        <item>pl:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwerty</item>
+        <item>ru:SupportTouchPositionCorrection</item>
+        <item>east_slavic</item>
+        <item>sr:SupportTouchPositionCorrection</item>
+        <item>south_slavic</item>
+        <item>sv:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>nordic</item>
+        <item>tr:AsciiCapable,SupportTouchPositionCorrection</item>
+        <item>qwerty</item>
+    </string-array>
+
     <!-- dictionary pack package name /settings activity (for shared prefs and settings) -->
     <string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string>
     <string name="dictionary_pack_settings_activity">com.google.android.inputmethod.latin.dictionarypack.DictionarySettingsActivity</string>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 0b781af79890576ea60b00dc4c4b570f0e9fcbe0..6c66a484404bcd787efb8732bf39a1f649dd3b43 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -85,11 +85,6 @@
     <!-- Description for option enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=65] -->
     <string name="use_contacts_dict_summary">Use names from Contacts for suggestions and corrections</string>
 
-    <!-- Option name for enabling insertion of suggestion spans (advanced option) [CHAR LIMIT=25] -->
-    <string name="enable_span_insert">Enable recorrections</string>
-    <!-- Option summary for enabling insertion of suggestion spans (advanced option) [CHAR LIMIT=65] -->
-    <string name="enable_span_insert_summary">Set suggestions for recorrections</string>
-
     <!-- Option to enable auto capitalization of sentences -->
     <string name="auto_cap">Auto-capitalization</string>
 
@@ -120,14 +115,10 @@
     <!-- Option to suggest auto correction suggestions very aggressively. Auto-corrects to a word which has even large edit distance from typed word. [CHAR LIMIT=20] -->
     <string name="auto_correction_threshold_mode_very_aggeressive">Very aggressive</string>
 
-    <!-- Option to enable next word correction -->
-    <string name="bigram_suggestion">Next word suggestions</string>
-    <!-- Option to enable next word suggestion. This uses the previous word in an attempt to improve the suggestions quality -->
-    <string name="bigram_suggestion_summary">Use previous word to improve suggestions</string>
-    <!-- Option to enable using next word prediction -->
-    <string name="bigram_prediction">Next word prediction</string>
-    <!-- Description for "next word prediction" option. This displays suggestions even when there is no input, based on the previous word. -->
-    <string name="bigram_prediction_summary">Use previous word also for prediction</string>
+    <!-- Option to enable using next word suggestions. After the user types a space, with this option on, the keyboard will try to predict the next word. -->
+    <string name="bigram_prediction">Next word suggestions</string>
+    <!-- Description for "next word suggestion" option. This displays suggestions even when there is no input, based on the previous word. -->
+    <string name="bigram_prediction_summary">Based on previous word</string>
 
     <!-- Indicates that a word has been added to the dictionary -->
     <string name="added_word"><xliff:g id="word">%s</xliff:g> : Saved</string>
@@ -305,7 +296,7 @@
     <string name="subtype_locale">Language</string>
     <!-- Title of the spinner for choosing a keyboard layout of custom style in the settings dialog [CHAR LIMIT=15] -->
     <string name="keyboard_layout_set">Layout</string>
-    <!-- The message of the dialog to note that a custom input style needs to be enabled. [CHAR LIMIT=64] -->
+    <!-- The message of the dialog to note that a custom input style needs to be enabled. [CHAR LIMIT=130] -->
     <string name="custom_input_style_note_message">"Your custom input style needs to be enabled before you start using it. Do you want to enable it now?"</string>
     <!-- Title of the button to enable a custom input style entry in the settings dialog [CHAR LIMIT=15] -->
     <string name="enable">Enable</string>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 07bff098be6bdc33f5ffb34da7bb0ecf8b274ba4..7f8a23a0eea5141c26f077703d2b419bf927ab9f 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -76,19 +76,19 @@
             android:label="@string/subtype_en_US"
             android:imeSubtypeLocale="en_US"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,TrySuppressingImeSwitcher,AsciiCapable"
+            android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_en_GB"
             android:imeSubtypeLocale="en_GB"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,TrySuppressingImeSwitcher,AsciiCapable"
+            android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ar"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=arabic"
+            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -112,19 +112,19 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="cs"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="da"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="de"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -136,7 +136,7 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="es"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -154,19 +154,19 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fi"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=azerty,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="fr_CA"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -178,13 +178,13 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="hr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="hu"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -196,14 +196,14 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="it"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. -->
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="iw"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=hebrew"
+            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -239,19 +239,19 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="nb"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="nl"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="pl"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -275,7 +275,7 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ru"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic"
+            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -293,13 +293,13 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="sr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=south_slavic"
+            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="sv"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
@@ -311,7 +311,7 @@
             android:label="@string/subtype_generic"
             android:imeSubtypeLocale="tr"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable"
+            android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection"
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index d8bf7847e75b4ebe9d98b9cd6be3af75bbf1eecc..bf8805875e5f901c55794579afea9f9260f01f14 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -80,6 +80,12 @@
     <PreferenceCategory
         android:title="@string/misc_category"
         android:key="misc_settings">
+        <CheckBoxPreference
+            android:key="next_word_prediction"
+            android:title="@string/bigram_prediction"
+            android:summary="@string/bigram_prediction_summary"
+            android:persistent="true"
+            android:defaultValue="true" />
         <CheckBoxPreference
             android:key="usability_study_mode"
             android:title="@string/prefs_usability_study_mode"
@@ -114,12 +120,6 @@
                 android:summary="@string/use_contacts_dict_summary"
                 android:persistent="true"
                 android:defaultValue="true" />
-            <CheckBoxPreference
-                android:key="next_word_prediction"
-                android:title="@string/bigram_prediction"
-                android:summary="@string/bigram_prediction_summary"
-                android:persistent="true"
-                android:defaultValue="true" />
             <PreferenceScreen
                 android:key="pref_vibration_duration_settings"
                 android:title="@string/prefs_keypress_vibration_duration_settings"/>
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 23acb8b749d22811f97475208d8220f2eff919e0..5ffd94a43e562b768492b7040378b7e445942c57 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.accessibility;
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.SparseIntArray;
 import android.view.inputmethod.EditorInfo;
 
 import com.android.inputmethod.keyboard.Key;
@@ -39,8 +40,8 @@ public class KeyCodeDescriptionMapper {
     // Map of key labels to spoken description resource IDs
     private final HashMap<CharSequence, Integer> mKeyLabelMap;
 
-    // Map of key codes to spoken description resource IDs
-    private final HashMap<Integer, Integer> mKeyCodeMap;
+    // Sparse array of spoken description resource IDs indexed by key codes
+    private final SparseIntArray mKeyCodeMap;
 
     public static void init() {
         sInstance.initInternal();
@@ -52,7 +53,7 @@ public class KeyCodeDescriptionMapper {
 
     private KeyCodeDescriptionMapper() {
         mKeyLabelMap = new HashMap<CharSequence, Integer>();
-        mKeyCodeMap = new HashMap<Integer, Integer>();
+        mKeyCodeMap = new SparseIntArray();
     }
 
     private void initInternal() {
@@ -60,7 +61,7 @@ public class KeyCodeDescriptionMapper {
         mKeyLabelMap.put(":-)", R.string.spoken_description_smiley);
 
         // Symbols that most TTS engines can't speak
-        mKeyCodeMap.put((int) ' ', R.string.spoken_description_space);
+        mKeyCodeMap.put(' ', R.string.spoken_description_space);
 
         // Special non-character codes defined in Keyboard
         mKeyCodeMap.put(Keyboard.CODE_DELETE, R.string.spoken_description_delete);
@@ -273,7 +274,8 @@ public class KeyCodeDescriptionMapper {
             return context.getString(OBSCURED_KEY_RES_ID);
         }
 
-        if (mKeyCodeMap.containsKey(code)) {
+        final int resId = mKeyCodeMap.get(code);
+        if (resId != 0) {
             return context.getString(mKeyCodeMap.get(code));
         } else if (isDefinedNonCtrl) {
             return Character.toString((char) code);
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 6d85fea27f158143c2edc2fd3d7d2f0051b932b9..1aec0012964e6eca8285d726d466d7be818c4495 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -23,6 +23,8 @@ import android.content.res.XmlResourceParser;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.util.TypedValue;
 import android.util.Xml;
 import android.view.InflateException;
@@ -44,7 +46,6 @@ import org.xmlpull.v1.XmlPullParserException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Locale;
 
@@ -134,7 +135,7 @@ public class Keyboard {
     public final Key[] mAltCodeKeysWhileTyping;
     public final KeyboardIconsSet mIconsSet;
 
-    private final HashMap<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
+    private final SparseArray<Key> mKeyCache = new SparseArray<Key>();
 
     private final ProximityInfo mProximityInfo;
     private final boolean mProximityCharsCorrectionEnabled;
@@ -202,7 +203,7 @@ public class Keyboard {
     }
 
     public boolean hasKey(Key aKey) {
-        if (mKeyCache.containsKey(aKey)) {
+        if (mKeyCache.indexOfValue(aKey) >= 0) {
             return true;
         }
 
@@ -346,8 +347,8 @@ public class Keyboard {
 
         private int mMaxHeightCount = 0;
         private int mMaxWidthCount = 0;
-        private final HashMap<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
-        private final HashMap<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
+        private final SparseIntArray mHeightHistogram = new SparseIntArray();
+        private final SparseIntArray mWidthHistogram = new SparseIntArray();
 
         private void clearHistogram() {
             mMostCommonKeyHeight = 0;
@@ -359,22 +360,22 @@ public class Keyboard {
             mWidthHistogram.clear();
         }
 
-        private static int updateHistogramCounter(HashMap<Integer, Integer> histogram,
-                Integer key) {
-            final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
+        private static int updateHistogramCounter(SparseIntArray histogram, int key) {
+            final int index = histogram.indexOfKey(key);
+            final int count = (index >= 0 ? histogram.get(key) : 0) + 1;
             histogram.put(key, count);
             return count;
         }
 
         private void updateHistogram(Key key) {
-            final Integer height = key.mHeight + key.mVerticalGap;
+            final int height = key.mHeight + key.mVerticalGap;
             final int heightCount = updateHistogramCounter(mHeightHistogram, height);
             if (heightCount > mMaxHeightCount) {
                 mMaxHeightCount = heightCount;
                 mMostCommonKeyHeight = height;
             }
 
-            final Integer width = key.mWidth + key.mHorizontalGap;
+            final int width = key.mWidth + key.mHorizontalGap;
             final int widthCount = updateHistogramCounter(mWidthHistogram, width);
             if (widthCount > mMaxWidthCount) {
                 mMaxWidthCount = widthCount;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 8c7246855b6cb8fb1a074f2cacd82df5501d3876..aab89a3e5e5b42db0301cf9d60abd775e3d55cd6 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -29,6 +29,7 @@ import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.text.InputType;
 import android.util.Log;
+import android.util.SparseArray;
 import android.util.Xml;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
@@ -116,9 +117,9 @@ public class KeyboardLayoutSet {
         InputMethodSubtype mSubtype;
         int mOrientation;
         int mWidth;
-        // KeyboardLayoutSet element id to element's parameters map.
-        final HashMap<Integer, ElementParams> mKeyboardLayoutSetElementIdToParamsMap =
-                new HashMap<Integer, ElementParams>();
+        // Sparse array of KeyboardLayoutSet element parameters indexed by element's id.
+        final SparseArray<ElementParams> mKeyboardLayoutSetElementIdToParamsMap =
+                new SparseArray<ElementParams>();
 
         static class ElementParams {
             int mKeyboardXmlId;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 18e01fb4982af13e691eac1351819a476d903609..fb98af3e655ac8ea4e272aa945b28dc4b6cc1f12 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -30,6 +30,7 @@ import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.os.Message;
 import android.util.AttributeSet;
+import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -42,7 +43,6 @@ import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
 import com.android.inputmethod.latin.StringUtils;
 
-import java.util.HashMap;
 import java.util.HashSet;
 
 /**
@@ -124,12 +124,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
     private Canvas mCanvas;
     private final Paint mPaint = new Paint();
     private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
-    // This map caches key label text height in pixel as value and key label text size as map key.
-    private static final HashMap<Integer, Float> sTextHeightCache =
-            new HashMap<Integer, Float>();
-    // This map caches key label text width in pixel as value and key label text size as map key.
-    private static final HashMap<Integer, Float> sTextWidthCache =
-            new HashMap<Integer, Float>();
+    // This sparse array caches key label text height in pixel indexed by key label text size.
+    private static final SparseArray<Float> sTextHeightCache = new SparseArray<Float>();
+    // This sparse array caches key label text width in pixel indexed by key label text size.
+    private static final SparseArray<Float> sTextWidthCache = new SparseArray<Float>();
     private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' };
     private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' };
 
@@ -766,7 +764,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
     private final Rect mTextBounds = new Rect();
 
     private float getCharHeight(char[] referenceChar, Paint paint) {
-        final Integer key = getCharGeometryCacheKey(referenceChar[0], paint);
+        final int key = getCharGeometryCacheKey(referenceChar[0], paint);
         final Float cachedValue = sTextHeightCache.get(key);
         if (cachedValue != null)
             return cachedValue;
@@ -778,7 +776,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
     }
 
     private float getCharWidth(char[] referenceChar, Paint paint) {
-        final Integer key = getCharGeometryCacheKey(referenceChar[0], paint);
+        final int key = getCharGeometryCacheKey(referenceChar[0], paint);
         final Float cachedValue = sTextWidthCache.get(key);
         if (cachedValue != null)
             return cachedValue;
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 383298de910911471df0c1b65af74fa7b54ecfa5..7714ba892d243106a8f6cfe9964c90203643fd87 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -127,7 +127,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         private static final int MSG_TYPING_STATE_EXPIRED = 4;
 
         private final KeyTimerParams mParams;
-        private boolean mInKeyRepeat;
 
         public KeyTimerHandler(LatinKeyboardView outerInstance, KeyTimerParams params) {
             super(outerInstance);
@@ -140,8 +139,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
             final PointerTracker tracker = (PointerTracker) msg.obj;
             switch (msg.what) {
             case MSG_REPEAT_KEY:
-                tracker.onRegisterKey(tracker.getKey());
-                startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
+                final Key currentKey = tracker.getKey();
+                if (currentKey != null && currentKey.mCode == msg.arg1) {
+                    tracker.onRegisterKey(currentKey);
+                    startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
+                }
                 break;
             case MSG_LONGPRESS_KEY:
                 if (tracker != null) {
@@ -158,22 +160,23 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         }
 
         private void startKeyRepeatTimer(PointerTracker tracker, long delay) {
-            sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker), delay);
+            final Key key = tracker.getKey();
+            if (key == null) return;
+            sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, key.mCode, 0, tracker), delay);
         }
 
         @Override
         public void startKeyRepeatTimer(PointerTracker tracker) {
-            mInKeyRepeat = true;
             startKeyRepeatTimer(tracker, mParams.mKeyRepeatStartTimeout);
         }
 
         public void cancelKeyRepeatTimer() {
-            mInKeyRepeat = false;
             removeMessages(MSG_REPEAT_KEY);
         }
 
+        // TODO: Suppress layout changes in key repeat mode
         public boolean isInKeyRepeat() {
-            return mInKeyRepeat;
+            return hasMessages(MSG_REPEAT_KEY);
         }
 
         @Override
@@ -451,8 +454,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
      */
     @Override
     public void setKeyboard(Keyboard keyboard) {
-        // Remove any pending messages, except dismissing preview
-        mKeyTimerHandler.cancelKeyTimers();
+        // Remove any pending messages, except dismissing preview and key repeat.
+        mKeyTimerHandler.cancelLongPressTimer();
         super.setKeyboard(keyboard);
         mKeyDetector.setKeyboard(
                 keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
@@ -755,15 +758,18 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
                 final PointerTracker tracker = PointerTracker.getPointerTracker(
                         pointerId, this);
                 final int px, py;
+                final MotionEvent motionEvent;
                 if (mMoreKeysPanel != null
                         && tracker.mPointerId == mMoreKeysPanelPointerTrackerId) {
                     px = mMoreKeysPanel.translateX((int)me.getX(i));
                     py = mMoreKeysPanel.translateY((int)me.getY(i));
+                    motionEvent = null;
                 } else {
                     px = (int)me.getX(i);
                     py = (int)me.getY(i);
+                    motionEvent = me;
                 }
-                tracker.onMoveEvent(px, py, eventTime);
+                tracker.onMoveEvent(px, py, eventTime, motionEvent);
                 if (ENABLE_USABILITY_STUDY_LOG) {
                     final float pointerSize = me.getSize(i);
                     final float pointerPressure = me.getPressure(i);
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 34e428e82c6d62857dbf467c6de07968dc9c725f..32ef408b409f9211e970e25dbd5b3d7b26d57042 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -148,9 +148,6 @@ public class PointerTracker {
     // true if this pointer has been long-pressed and is showing a more keys panel.
     private boolean mIsShowingMoreKeysPanel;
 
-    // true if this pointer is repeatable key
-    private boolean mIsRepeatableKey;
-
     // true if this pointer is in sliding key input
     boolean mIsInSlidingKeyInput;
 
@@ -319,6 +316,13 @@ public class PointerTracker {
     private void setKeyDetectorInner(KeyDetector keyDetector) {
         mKeyDetector = keyDetector;
         mKeyboard = keyDetector.getKeyboard();
+        final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
+        if (newKey != mCurrentKey) {
+            if (mDrawingProxy != null) {
+                setReleasedKeyGraphics(mCurrentKey);
+            }
+            mCurrentKey = newKey;
+        }
         final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4;
         mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
     }
@@ -465,7 +469,7 @@ public class PointerTracker {
             onUpEvent(x, y, eventTime);
             break;
         case MotionEvent.ACTION_MOVE:
-            onMoveEvent(x, y, eventTime);
+            onMoveEvent(x, y, eventTime, null);
             break;
         case MotionEvent.ACTION_CANCEL:
             onCancelEvent(x, y, eventTime);
@@ -521,7 +525,6 @@ public class PointerTracker {
                 || mKeyDetector.alwaysAllowsSlidingInput();
         mKeyboardLayoutHasBeenChanged = false;
         mKeyAlreadyProcessed = false;
-        mIsRepeatableKey = false;
         mIsInSlidingKeyInput = false;
         mIgnoreModifierKey = false;
         if (key != null) {
@@ -545,7 +548,7 @@ public class PointerTracker {
         mIsInSlidingKeyInput = true;
     }
 
-    public void onMoveEvent(int x, int y, long eventTime) {
+    public void onMoveEvent(int x, int y, long eventTime, MotionEvent me) {
         if (DEBUG_MOVE_EVENT)
             printTouchEvent("onMoveEvent:", x, y, eventTime);
         if (mKeyAlreadyProcessed)
@@ -668,7 +671,7 @@ public class PointerTracker {
         }
         if (mKeyAlreadyProcessed)
             return;
-        if (!mIsRepeatableKey) {
+        if (mCurrentKey != null && !mCurrentKey.isRepeatable()) {
             detectAndSendKey(mCurrentKey, mKeyX, mKeyY);
         }
     }
@@ -714,9 +717,6 @@ public class PointerTracker {
         if (key != null && key.isRepeatable()) {
             onRegisterKey(key);
             mTimerProxy.startKeyRepeatTimer(this);
-            mIsRepeatableKey = true;
-        } else {
-            mIsRepeatableKey = false;
         }
     }
 
@@ -760,14 +760,10 @@ public class PointerTracker {
         callListenerOnRelease(key, code, false);
     }
 
-    private long mPreviousEventTime;
-
     private void printTouchEvent(String title, int x, int y, long eventTime) {
         final Key key = mKeyDetector.detectHitKey(x, y);
         final String code = KeyDetector.printableCode(key);
-        final long delta = eventTime - mPreviousEventTime;
         Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %s", title,
-                (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, code));
-        mPreviousEventTime = eventTime;
+                (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, eventTime, code));
     }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 1bc825479293d18da5aa473e0890fb93ccf0cd4e..ae123e29aa157a13cb7f935e873c68414c67da28 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -24,7 +24,6 @@ import com.android.inputmethod.keyboard.Keyboard.Params.TouchPositionCorrection;
 import com.android.inputmethod.latin.JniUtils;
 
 import java.util.Arrays;
-import java.util.HashMap;
 
 public class ProximityInfo {
     /** MAX_PROXIMITY_CHARS_SIZE must be the same as MAX_PROXIMITY_CHARS_SIZE_INTERNAL
@@ -190,10 +189,6 @@ public class ProximityInfo {
     private void computeNearestNeighbors() {
         final int defaultWidth = mMostCommonKeyWidth;
         final Key[] keys = mKeys;
-        final HashMap<Integer, Key> keyCodeMap = new HashMap<Integer, Key>();
-        for (final Key key : keys) {
-            keyCodeMap.put(key.mCode, key);
-        }
         final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
         final int threshold = thresholdBase * thresholdBase;
         // Round-up so we don't have any pixels outside the grid
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 80f4f259b1a7b325b4ad89b93d1d885ad4787b43..291b3b943891ed8ba8f7c8bb57078d92c1c9bebd 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard.internal;
 
 import android.content.res.TypedArray;
 import android.util.Log;
+import android.util.SparseArray;
 
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.latin.R;
@@ -89,7 +90,7 @@ public class KeyStyles {
 
     private class DeclaredKeyStyle extends KeyStyle {
         private final String mParentStyleName;
-        private final HashMap<Integer, Object> mStyleAttributes = new HashMap<Integer, Object>();
+        private final SparseArray<Object> mStyleAttributes = new SparseArray<Object>();
 
         public DeclaredKeyStyle(String parentStyleName) {
             mParentStyleName = parentStyleName;
@@ -100,8 +101,9 @@ public class KeyStyles {
             if (a.hasValue(index)) {
                 return parseStringArray(a, index);
             }
-            if (mStyleAttributes.containsKey(index)) {
-                return (String[])mStyleAttributes.get(index);
+            final Object value = mStyleAttributes.get(index);
+            if (value != null) {
+                return (String[])value;
             }
             final KeyStyle parentStyle = mStyles.get(mParentStyleName);
             return parentStyle.getStringArray(a, index);
@@ -112,8 +114,9 @@ public class KeyStyles {
             if (a.hasValue(index)) {
                 return parseString(a, index);
             }
-            if (mStyleAttributes.containsKey(index)) {
-                return (String)mStyleAttributes.get(index);
+            final Object value = mStyleAttributes.get(index);
+            if (value != null) {
+                return (String)value;
             }
             final KeyStyle parentStyle = mStyles.get(mParentStyleName);
             return parentStyle.getString(a, index);
@@ -124,8 +127,9 @@ public class KeyStyles {
             if (a.hasValue(index)) {
                 return a.getInt(index, defaultValue);
             }
-            if (mStyleAttributes.containsKey(index)) {
-                return (Integer)mStyleAttributes.get(index);
+            final Object value = mStyleAttributes.get(index);
+            if (value != null) {
+                return (Integer)value;
             }
             final KeyStyle parentStyle = mStyles.get(mParentStyleName);
             return parentStyle.getInt(a, index, defaultValue);
@@ -133,12 +137,13 @@ public class KeyStyles {
 
         @Override
         public int getFlag(TypedArray a, int index) {
-            int value = a.getInt(index, 0);
-            if (mStyleAttributes.containsKey(index)) {
-                value |= (Integer)mStyleAttributes.get(index);
+            int flags = a.getInt(index, 0);
+            final Object value = mStyleAttributes.get(index);
+            if (value != null) {
+                flags |= (Integer)value;
             }
             final KeyStyle parentStyle = mStyles.get(mParentStyleName);
-            return value | parentStyle.getFlag(a, index);
+            return flags | parentStyle.getFlag(a, index);
         }
 
         void readKeyAttributes(TypedArray keyAttr) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 540e63b3f3040f2cbdd5aba9bef20fcc377c0285..5155851fedeb9bcc4ece10f07c346477b3679c0a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -20,6 +20,7 @@ import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
+import android.util.SparseIntArray;
 
 import com.android.inputmethod.latin.R;
 
@@ -31,8 +32,7 @@ public class KeyboardIconsSet {
     public static final int ICON_UNDEFINED = 0;
     private static final int ATTR_UNDEFINED = 0;
 
-    private static final HashMap<Integer, Integer> ATTR_ID_TO_ICON_ID
-            = new HashMap<Integer, Integer>();
+    private static final SparseIntArray ATTR_ID_TO_ICON_ID = new SparseIntArray();
 
     // Icon name to icon id map.
     private static final HashMap<String, Integer> sNameToIdsMap = new HashMap<String, Integer>();
@@ -76,7 +76,9 @@ public class KeyboardIconsSet {
     }
 
     public void loadIcons(final TypedArray keyboardAttrs) {
-        for (final Integer attrId : ATTR_ID_TO_ICON_ID.keySet()) {
+        final int size = ATTR_ID_TO_ICON_ID.size();
+        for (int index = 0; index < size; index++) {
+            final int attrId = ATTR_ID_TO_ICON_ID.keyAt(index);
             try {
                 final Drawable icon = keyboardAttrs.getDrawable(attrId);
                 setDefaultBounds(icon);
diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java
index e0452483c9ca3c71ff577dba7b2b666bb2ac4206..c78974dac1addf7da2a5b18edd37d12e4ad84931 100644
--- a/java/src/com/android/inputmethod/latin/AutoCorrection.java
+++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java
@@ -21,34 +21,17 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import android.text.TextUtils;
 import android.util.Log;
 
-import java.util.ArrayList;
 import java.util.concurrent.ConcurrentHashMap;
 
 public class AutoCorrection {
     private static final boolean DBG = LatinImeLogger.sDBG;
     private static final String TAG = AutoCorrection.class.getSimpleName();
+    private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
 
     private AutoCorrection() {
         // Purely static class: can't instantiate.
     }
 
-    public static CharSequence computeAutoCorrectionWord(
-            final ConcurrentHashMap<String, Dictionary> dictionaries,
-            final WordComposer wordComposer, final ArrayList<SuggestedWordInfo> suggestions,
-            final CharSequence consideredWord, final float autoCorrectionThreshold,
-            final CharSequence whitelistedWord) {
-        if (hasAutoCorrectionForWhitelistedWord(whitelistedWord)) {
-            return whitelistedWord;
-        } else if (hasAutoCorrectionForConsideredWord(
-                dictionaries, wordComposer, suggestions, consideredWord)) {
-            return consideredWord;
-        } else if (hasAutoCorrectionForBinaryDictionary(wordComposer, suggestions,
-                consideredWord, autoCorrectionThreshold)) {
-            return suggestions.get(0).mWord;
-        }
-        return null;
-    }
-
     public static boolean isValidWord(final ConcurrentHashMap<String, Dictionary> dictionaries,
             CharSequence word, boolean ignoreCase) {
         if (TextUtils.isEmpty(word)) {
@@ -56,7 +39,7 @@ public class AutoCorrection {
         }
         final CharSequence lowerCasedWord = word.toString().toLowerCase();
         for (final String key : dictionaries.keySet()) {
-            if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue;
+            if (key.equals(Dictionary.TYPE_WHITELIST)) continue;
             final Dictionary dictionary = dictionaries.get(key);
             // It's unclear how realistically 'dictionary' can be null, but the monkey is somehow
             // managing to get null in here. Presumably the language is changing to a language with
@@ -81,7 +64,7 @@ public class AutoCorrection {
         }
         int maxFreq = -1;
         for (final String key : dictionaries.keySet()) {
-            if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue;
+            if (key.equals(Dictionary.TYPE_WHITELIST)) continue;
             final Dictionary dictionary = dictionaries.get(key);
             if (null == dictionary) continue;
             final int tempFreq = dictionary.getFrequency(word);
@@ -92,11 +75,12 @@ public class AutoCorrection {
         return maxFreq;
     }
 
-    public static boolean allowsToBeAutoCorrected(
+    // Returns true if this is a whitelist entry, or it isn't in any dictionary.
+    public static boolean isWhitelistedOrNotAWord(
             final ConcurrentHashMap<String, Dictionary> dictionaries,
             final CharSequence word, final boolean ignoreCase) {
         final WhitelistDictionary whitelistDictionary =
-                (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST);
+                (WhitelistDictionary)dictionaries.get(Dictionary.TYPE_WHITELIST);
         // If "word" is in the whitelist dictionary, it should not be auto corrected.
         if (whitelistDictionary != null
                 && whitelistDictionary.shouldForciblyAutoCorrectFrom(word)) {
@@ -105,33 +89,18 @@ public class AutoCorrection {
         return !isValidWord(dictionaries, word, ignoreCase);
     }
 
-    private static boolean hasAutoCorrectionForWhitelistedWord(CharSequence whiteListedWord) {
-        return whiteListedWord != null;
-    }
-
-    private static boolean hasAutoCorrectionForConsideredWord(
-            final ConcurrentHashMap<String, Dictionary> dictionaries,
-            final WordComposer wordComposer, final ArrayList<SuggestedWordInfo> suggestions,
-            final CharSequence consideredWord) {
-        if (TextUtils.isEmpty(consideredWord)) return false;
-        return wordComposer.size() > 1 && suggestions.size() > 0
-                && !allowsToBeAutoCorrected(dictionaries, consideredWord, false);
-    }
-
-    private static boolean hasAutoCorrectionForBinaryDictionary(WordComposer wordComposer,
-            ArrayList<SuggestedWordInfo> suggestions,
+    public static boolean suggestionExceedsAutoCorrectionThreshold(SuggestedWordInfo suggestion,
             CharSequence consideredWord, float autoCorrectionThreshold) {
-        if (wordComposer.size() > 1 && suggestions.size() > 0) {
-            final SuggestedWordInfo autoCorrectionSuggestion = suggestions.get(0);
+        if (null != suggestion) {
             //final int autoCorrectionSuggestionScore = sortedScores[0];
-            final int autoCorrectionSuggestionScore = autoCorrectionSuggestion.mScore;
+            final int autoCorrectionSuggestionScore = suggestion.mScore;
             // TODO: when the normalized score of the first suggestion is nearly equals to
             //       the normalized score of the second suggestion, behave less aggressive.
             final float normalizedScore = BinaryDictionary.calcNormalizedScore(
-                    consideredWord.toString(), autoCorrectionSuggestion.mWord.toString(),
+                    consideredWord.toString(), suggestion.mWord.toString(),
                     autoCorrectionSuggestionScore);
             if (DBG) {
-                Log.d(TAG, "Normalized " + consideredWord + "," + autoCorrectionSuggestion + ","
+                Log.d(TAG, "Normalized " + consideredWord + "," + suggestion + ","
                         + autoCorrectionSuggestionScore + ", " + normalizedScore
                         + "(" + autoCorrectionThreshold + ")");
             }
@@ -139,10 +108,43 @@ public class AutoCorrection {
                 if (DBG) {
                     Log.d(TAG, "Auto corrected by S-threshold.");
                 }
-                return true;
+                return !shouldBlockAutoCorrectionBySafetyNet(consideredWord.toString(),
+                        suggestion.mWord);
             }
         }
         return false;
     }
 
+    // TODO: Resolve the inconsistencies between the native auto correction algorithms and
+    // this safety net
+    public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord,
+            final CharSequence suggestion) {
+        // Safety net for auto correction.
+        // Actually if we hit this safety net, it's a bug.
+        // If user selected aggressive auto correction mode, there is no need to use the safety
+        // net.
+        // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
+        // we should not use net because relatively edit distance can be big.
+        final int typedWordLength = typedWord.length();
+        if (typedWordLength < MINIMUM_SAFETY_NET_CHAR_LENGTH) {
+            return false;
+        }
+        final int maxEditDistanceOfNativeDictionary =
+                (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1;
+        final int distance = BinaryDictionary.editDistance(typedWord, suggestion.toString());
+        if (DBG) {
+            Log.d(TAG, "Autocorrected edit distance = " + distance
+                    + ", " + maxEditDistanceOfNativeDictionary);
+        }
+        if (distance > maxEditDistanceOfNativeDictionary) {
+            if (DBG) {
+                Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestion);
+                Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. "
+                        + "Turning off auto-correction.");
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index d0613bd722baaa421fde1af8985a0f28bb49da67..ae415d0ab1ae155095f459155a7b9b2fff922c2c 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -20,7 +20,9 @@ import android.content.Context;
 import android.text.TextUtils;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Locale;
 
@@ -40,17 +42,18 @@ public class BinaryDictionary extends Dictionary {
      */
     public static final int MAX_WORD_LENGTH = 48;
     public static final int MAX_WORDS = 18;
+    public static final int MAX_SPACES = 16;
 
     private static final String TAG = "BinaryDictionary";
     private static final int MAX_BIGRAMS = 60;
 
     private static final int TYPED_LETTER_MULTIPLIER = 2;
 
-    private int mDicTypeId;
     private long mNativeDict;
     private final int[] mInputCodes = new int[MAX_WORD_LENGTH];
     private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
     private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
+    private final int[] mSpaceIndices = new int[MAX_SPACES];
     private final int[] mScores = new int[MAX_WORDS];
     private final int[] mBigramScores = new int[MAX_BIGRAMS];
 
@@ -65,14 +68,12 @@ public class BinaryDictionary extends Dictionary {
      * @param offset the offset of the dictionary data within the file.
      * @param length the length of the binary data.
      * @param useFullEditDistance whether to use the full edit distance in suggestions
+     * @param dictType the dictionary type, as a human-readable string
      */
     public BinaryDictionary(final Context context,
             final String filename, final long offset, final long length,
-            final boolean useFullEditDistance, final Locale locale) {
-        // Note: at the moment a binary dictionary is always of the "main" type.
-        // Initializing this here will help transitioning out of the scheme where
-        // the Suggest class knows everything about every single dictionary.
-        mDicTypeId = Suggest.DIC_MAIN;
+            final boolean useFullEditDistance, final Locale locale, final String dictType) {
+        super(dictType);
         mUseFullEditDistance = useFullEditDistance;
         loadDictionary(filename, offset, length);
     }
@@ -87,8 +88,10 @@ public class BinaryDictionary extends Dictionary {
     private native int getFrequencyNative(long dict, int[] word, int wordLength);
     private native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
     private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
-            int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams,
-            boolean useFullEditDistance, char[] outputChars, int[] scores);
+            int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodes, int codesSize,
+            int commitPoint, boolean isGesture,
+            int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars,
+            int[] scores, int[] outputIndices);
     private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength,
             int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
             int maxWordLength, int maxBigrams);
@@ -103,9 +106,9 @@ public class BinaryDictionary extends Dictionary {
     }
 
     @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
-        if (mNativeDict == 0) return;
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+            final CharSequence previousWord) {
+        if (mNativeDict == 0) return null;
 
         int[] codePoints = StringUtils.toCodePointArray(previousWord.toString());
         Arrays.fill(mOutputChars_bigrams, (char) 0);
@@ -123,6 +126,7 @@ public class BinaryDictionary extends Dictionary {
             count = MAX_BIGRAMS;
         }
 
+        final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
         for (int j = 0; j < count; ++j) {
             if (codesSize > 0 && mBigramScores[j] < 1) break;
             final int start = j * MAX_WORD_LENGTH;
@@ -131,19 +135,22 @@ public class BinaryDictionary extends Dictionary {
                 ++len;
             }
             if (len > 0) {
-                callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j],
-                        mDicTypeId, Dictionary.BIGRAM);
+                suggestions.add(new SuggestedWordInfo(
+                        new String(mOutputChars_bigrams, start, len),
+                        mBigramScores[j], SuggestedWordInfo.KIND_CORRECTION, mDictType));
             }
         }
+        return suggestions;
     }
 
     // proximityInfo and/or prevWordForBigrams may not be null.
     @Override
-    public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
         final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars,
-                mScores);
+                mScores, mSpaceIndices);
 
+        final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
         for (int j = 0; j < count; ++j) {
             if (mScores[j] < 1) break;
             final int start = j * MAX_WORD_LENGTH;
@@ -152,10 +159,13 @@ public class BinaryDictionary extends Dictionary {
                 ++len;
             }
             if (len > 0) {
-                callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId,
-                        Dictionary.UNIGRAM);
+                // TODO: actually get the kind from native code
+                suggestions.add(new SuggestedWordInfo(
+                        new String(mOutputChars, start, len),
+                        mScores[j], SuggestedWordInfo.KIND_CORRECTION, mDictType));
             }
         }
+        return suggestions;
     }
 
     /* package for test */ boolean isValidDictionary() {
@@ -165,7 +175,7 @@ public class BinaryDictionary extends Dictionary {
     // proximityInfo may not be null.
     /* package for test */ int getSuggestions(final WordComposer codes,
             final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo,
-            char[] outputChars, int[] scores) {
+            char[] outputChars, int[] scores, int[] spaceIndices) {
         if (!isValidDictionary()) return -1;
 
         final int codesSize = codes.size();
@@ -179,14 +189,22 @@ public class BinaryDictionary extends Dictionary {
         Arrays.fill(outputChars, (char) 0);
         Arrays.fill(scores, 0);
 
-        final int[] prevWordCodePointArray = null == prevWordForBigrams
+        // TODO: toLowerCase in the native code
+        final int[] prevWordCodePointArray = (null == prevWordForBigrams)
                 ? null : StringUtils.toCodePointArray(prevWordForBigrams.toString());
 
-        // TODO: pass the previous word to native code
-        return getSuggestionsNative(
-                mNativeDict, proximityInfo.getNativeProximityInfo(),
-                codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize,
-                prevWordCodePointArray, mUseFullEditDistance, outputChars, scores);
+        int[] emptyArray = new int[codesSize];
+        Arrays.fill(emptyArray, 0);
+
+        //final int commitPoint = codes.getCommitPoint();
+        //codes.clearCommitPoint();
+
+        final InputPointers ips = codes.getInputPointers();
+
+        return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
+            ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(),
+            mInputCodes, codesSize, 0 /* unused */, false, prevWordCodePointArray,
+            mUseFullEditDistance, outputChars, scores, spaceIndices);
     }
 
     public static float calcNormalizedScore(String before, String after, int score) {
diff --git a/java/src/com/android/inputmethod/latin/BoundedTreeSet.java b/java/src/com/android/inputmethod/latin/BoundedTreeSet.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf977617d111af7f4e39cad7eb395e6d423b2d45
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/BoundedTreeSet.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.TreeSet;
+
+/**
+ * A TreeSet that is bounded in size and throws everything that's smaller than its limit
+ */
+public class BoundedTreeSet extends TreeSet<SuggestedWordInfo> {
+    private final int mCapacity;
+    public BoundedTreeSet(final Comparator<SuggestedWordInfo> comparator, final int capacity) {
+        super(comparator);
+        mCapacity = capacity;
+    }
+
+    @Override
+    public boolean add(final SuggestedWordInfo e) {
+        if (size() < mCapacity) return super.add(e);
+        if (comparator().compare(e, last()) > 0) return false;
+        super.add(e);
+        pollLast(); // removes the last element
+        return true;
+    }
+
+    @Override
+    public boolean addAll(final Collection<? extends SuggestedWordInfo> e) {
+        if (null == e) return false;
+        return super.addAll(e);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 10e511eaff82c180664ed6593b0acdc1cef08f0b..5edc4314fcc53ae2ec5e4f57a575cc8641dd990e 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -62,8 +62,8 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
      */
     private final boolean mUseFirstLastBigrams;
 
-    public ContactsBinaryDictionary(final Context context, final int dicTypeId, Locale locale) {
-        super(context, getFilenameWithLocale(NAME, locale.toString()), dicTypeId);
+    public ContactsBinaryDictionary(final Context context, Locale locale) {
+        super(context, getFilenameWithLocale(NAME, locale.toString()), Dictionary.TYPE_CONTACTS);
         mLocale = locale;
         mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
         registerObserver(context);
@@ -120,12 +120,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
         }
     }
 
-    @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
-        super.getBigrams(codes, previousWord, callback);
-    }
-
     private boolean useFirstLastBigramsForLocale(Locale locale) {
         // TODO: Add firstname/lastname bigram rules for other languages.
         if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
@@ -167,7 +161,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
      * bigrams depending on locale.
      */
     private void addName(String name) {
-        int len = name.codePointCount(0, name.length());
+        int len = StringUtils.codePointCount(name);
         String prevWord = null;
         // TODO: Better tokenization for non-Latin writing systems
         for (int i = 0; i < len; i++) {
@@ -177,7 +171,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
                 i = end - 1;
                 // Don't add single letter words, possibly confuses
                 // capitalization of i.
-                final int wordLen = word.codePointCount(0, word.length());
+                final int wordLen = StringUtils.codePointCount(word);
                 if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
                     super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS);
                     if (!TextUtils.isEmpty(prevWord)) {
@@ -266,14 +260,14 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
      * Checks if the words in a name are in the current binary dictionary.
      */
     private boolean isNameInDictionary(String name) {
-        int len = name.codePointCount(0, name.length());
+        int len = StringUtils.codePointCount(name);
         String prevWord = null;
         for (int i = 0; i < len; i++) {
             if (Character.isLetter(name.codePointAt(i))) {
                 int end = getWordEndPosition(name, len, i);
                 String word = name.substring(i, end);
                 i = end - 1;
-                final int wordLen = word.codePointCount(0, word.length());
+                final int wordLen = StringUtils.codePointCount(word);
                 if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
                     if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) {
                         if (!super.isValidBigramLocked(prevWord, word)) {
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index 9c3d46e70eab814fa4521ce5685677c41b4df9c0..0835450c1236d23d3dc057318fb707e5b98138a0 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -17,6 +17,9 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
 
 /**
  * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
@@ -28,55 +31,43 @@ public abstract class Dictionary {
      */
     protected static final int FULL_WORD_SCORE_MULTIPLIER = 2;
 
-    public static final int UNIGRAM = 0;
-    public static final int BIGRAM = 1;
-
     public static final int NOT_A_PROBABILITY = -1;
-    /**
-     * Interface to be implemented by classes requesting words to be fetched from the dictionary.
-     * @see #getWords(WordComposer, CharSequence, WordCallback, ProximityInfo)
-     */
-    public interface WordCallback {
-        /**
-         * Adds a word to a list of suggestions. The word is expected to be ordered based on
-         * the provided score.
-         * @param word the character array containing the word
-         * @param wordOffset starting offset of the word in the character array
-         * @param wordLength length of valid characters in the character array
-         * @param score the score of occurrence. This is normalized between 1 and 255, but
-         * can exceed those limits
-         * @param dicTypeId of the dictionary where word was from
-         * @param dataType tells type of this data, either UNIGRAM or BIGRAM
-         * @return true if the word was added, false if no more words are required
-         */
-        boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId,
-                int dataType);
+
+    public static final String TYPE_USER_TYPED = "user_typed";
+    public static final String TYPE_APPLICATION_DEFINED = "application_defined";
+    public static final String TYPE_HARDCODED = "hardcoded"; // punctuation signs and such
+    public static final String TYPE_MAIN = "main";
+    public static final String TYPE_CONTACTS = "contacts";
+    // User dictionary, the system-managed one.
+    public static final String TYPE_USER = "user";
+    // User history dictionary internal to LatinIME.
+    public static final String TYPE_USER_HISTORY = "history";
+    public static final String TYPE_WHITELIST ="whitelist";
+    protected final String mDictType;
+
+    public Dictionary(final String dictType) {
+        mDictType = dictType;
     }
 
     /**
      * Searches for words in the dictionary that match the characters in the composer. Matched
-     * words are added through the callback object.
-     * @param composer the key sequence to match
+     * words are returned as an ArrayList.
+     * @param composer the key sequence to match with coordinate info, as a WordComposer
      * @param prevWordForBigrams the previous word, or null if none
-     * @param callback the callback object to send matched words to as possible candidates
      * @param proximityInfo the object for key proximity. May be ignored by some implementations.
-     * @see WordCallback#addWord(char[], int, int, int, int, int)
+     * @return the list of suggestions
      */
-    abstract public void getWords(final WordComposer composer,
-            final CharSequence prevWordForBigrams, final WordCallback callback,
-            final ProximityInfo proximityInfo);
+    abstract public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo);
 
     /**
-     * Searches for pairs in the bigram dictionary that matches the previous word and all the
-     * possible words following are added through the callback object.
+     * Searches for pairs in the bigram dictionary that matches the previous word.
      * @param composer the key sequence to match
      * @param previousWord the word before
-     * @param callback the callback object to send possible word following previous word
+     * @return the list of suggestions
      */
-    public void getBigrams(final WordComposer composer, final CharSequence previousWord,
-            final WordCallback callback) {
-        // empty base implementation
-    }
+    public abstract ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+            final CharSequence previousWord);
 
     /**
      * Checks if the given word occurs in the dictionary
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 26c2e637e6a1130b3ab78f222eae83892200bc93..dcc53c59f98780d7bc3923dada8a7f0ce0f52361 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -17,9 +17,11 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -31,11 +33,13 @@ public class DictionaryCollection extends Dictionary {
     private final String TAG = DictionaryCollection.class.getSimpleName();
     protected final CopyOnWriteArrayList<Dictionary> mDictionaries;
 
-    public DictionaryCollection() {
+    public DictionaryCollection(final String dictType) {
+        super(dictType);
         mDictionaries = new CopyOnWriteArrayList<Dictionary>();
     }
 
-    public DictionaryCollection(Dictionary... dictionaries) {
+    public DictionaryCollection(final String dictType, Dictionary... dictionaries) {
+        super(dictType);
         if (null == dictionaries) {
             mDictionaries = new CopyOnWriteArrayList<Dictionary>();
         } else {
@@ -44,23 +48,48 @@ public class DictionaryCollection extends Dictionary {
         }
     }
 
-    public DictionaryCollection(Collection<Dictionary> dictionaries) {
+    public DictionaryCollection(final String dictType, Collection<Dictionary> dictionaries) {
+        super(dictType);
         mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries);
         mDictionaries.removeAll(Collections.singleton(null));
     }
 
     @Override
-    public void getWords(final WordComposer composer, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
-        for (final Dictionary dict : mDictionaries)
-            dict.getWords(composer, prevWordForBigrams, callback, proximityInfo);
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
+        final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+        if (dictionaries.isEmpty()) return null;
+        // To avoid creating unnecessary objects, we get the list out of the first
+        // dictionary and add the rest to it if not null, hence the get(0)
+        ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getWords(composer,
+                prevWordForBigrams, proximityInfo);
+        if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+        final int length = dictionaries.size();
+        for (int i = 0; i < length; ++ i) {
+            final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getWords(composer,
+                    prevWordForBigrams, proximityInfo);
+            if (null != sugg) suggestions.addAll(sugg);
+        }
+        return suggestions;
     }
 
     @Override
-    public void getBigrams(final WordComposer composer, final CharSequence previousWord,
-            final WordCallback callback) {
-        for (final Dictionary dict : mDictionaries)
-            dict.getBigrams(composer, previousWord, callback);
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+            final CharSequence previousWord) {
+        final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+        if (dictionaries.isEmpty()) return null;
+        // To avoid creating unnecessary objects, we get the list out of the first
+        // dictionary and add the rest to it if not null, hence the get(0)
+        ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getBigrams(composer,
+                previousWord);
+        if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+        final int length = dictionaries.size();
+        for (int i = 0; i < length; ++ i) {
+            final ArrayList<SuggestedWordInfo> sugg =
+                   dictionaries.get(i).getBigrams(composer, previousWord);
+            if (null != sugg) suggestions.addAll(sugg);
+        }
+        return suggestions;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index a22d73af764bb8b4f8ba1e35f0d134beb12cf46a..06a5f4b72b556376349c32e158634bb2608984cd 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -49,7 +49,8 @@ public class DictionaryFactory {
             final Locale locale, final boolean useFullEditDistance) {
         if (null == locale) {
             Log.e(TAG, "No locale defined for dictionary");
-            return new DictionaryCollection(createBinaryDictionary(context, locale));
+            return new DictionaryCollection(Dictionary.TYPE_MAIN,
+                    createBinaryDictionary(context, locale));
         }
 
         final LinkedList<Dictionary> dictList = new LinkedList<Dictionary>();
@@ -59,7 +60,7 @@ public class DictionaryFactory {
             for (final AssetFileAddress f : assetFileList) {
                 final BinaryDictionary binaryDictionary =
                         new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength,
-                                useFullEditDistance, locale);
+                                useFullEditDistance, locale, Dictionary.TYPE_MAIN);
                 if (binaryDictionary.isValidDictionary()) {
                     dictList.add(binaryDictionary);
                 }
@@ -69,7 +70,7 @@ public class DictionaryFactory {
         // If the list is empty, that means we should not use any dictionary (for example, the user
         // explicitly disabled the main dictionary), so the following is okay. dictList is never
         // null, but if for some reason it is, DictionaryCollection handles it gracefully.
-        return new DictionaryCollection(dictList);
+        return new DictionaryCollection(Dictionary.TYPE_MAIN, dictList);
     }
 
     /**
@@ -112,7 +113,7 @@ public class DictionaryFactory {
                 return null;
             }
             return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(),
-                    false /* useFullEditDistance */, locale);
+                    false /* useFullEditDistance */, locale, Dictionary.TYPE_MAIN);
         } catch (android.content.res.Resources.NotFoundException e) {
             Log.e(TAG, "Could not find the resource");
             return null;
@@ -140,7 +141,7 @@ public class DictionaryFactory {
             long startOffset, long length, final boolean useFullEditDistance, Locale locale) {
         if (dictionary.isFile()) {
             return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length,
-                    useFullEditDistance, locale);
+                    useFullEditDistance, locale, Dictionary.TYPE_MAIN);
         } else {
             Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath());
             return null;
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c65404cbc2d61781512e2290a107548f905b0400..1cda9f25736601ed7f0b8beaa9d976f136a98664 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -19,6 +19,7 @@ import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.makedict.BinaryDictInputOutput;
 import com.android.inputmethod.latin.makedict.FusionDictionary;
 import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
@@ -75,9 +76,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     /** The expandable fusion dictionary used to generate the binary dictionary. */
     private FusionDictionary mFusionDictionary;
 
-    /** The dictionary type id. */
-    public final int mDicTypeId;
-
     /**
      * The name of this dictionary, used as the filename for storing the binary dictionary. Multiple
      * dictionary instances with the same filename is supported, with access controlled by
@@ -123,11 +121,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
      * @param context The application context of the parent.
      * @param filename The filename for this binary dictionary. Multiple dictionaries with the same
      *        filename is supported.
-     * @param dictType The type of this dictionary.
+     * @param dictType the dictionary type, as a human-readable string
      */
     public ExpandableBinaryDictionary(
-            final Context context, final String filename, final int dictType) {
-        mDicTypeId = dictType;
+            final Context context, final String filename, final String dictType) {
+        super(dictType);
         mFilename = filename;
         mContext = context;
         mBinaryDictionary = null;
@@ -194,46 +192,47 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     }
 
     @Override
-    public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
         asyncReloadDictionaryIfRequired();
-        getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+        return getWordsInner(codes, prevWordForBigrams, proximityInfo);
     }
 
-    protected final void getWordsInner(final WordComposer codes,
-            final CharSequence prevWordForBigrams, final WordCallback callback,
-            final ProximityInfo proximityInfo) {
+    protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
         // Ensure that there are no concurrent calls to getWords. If there are, do nothing and
         // return.
         if (mLocalDictionaryController.tryLock()) {
             try {
                 if (mBinaryDictionary != null) {
-                    mBinaryDictionary.getWords(codes, prevWordForBigrams, callback, proximityInfo);
+                    return mBinaryDictionary.getWords(codes, prevWordForBigrams, proximityInfo);
                 }
             } finally {
                 mLocalDictionaryController.unlock();
             }
         }
+        return null;
     }
 
     @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+            final CharSequence previousWord) {
         asyncReloadDictionaryIfRequired();
-        getBigramsInner(codes, previousWord, callback);
+        return getBigramsInner(codes, previousWord);
     }
 
-    protected void getBigramsInner(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
+    protected ArrayList<SuggestedWordInfo> getBigramsInner(final WordComposer codes,
+            final CharSequence previousWord) {
         if (mLocalDictionaryController.tryLock()) {
             try {
                 if (mBinaryDictionary != null) {
-                    mBinaryDictionary.getBigrams(codes, previousWord, callback);
+                    return mBinaryDictionary.getBigrams(codes, previousWord);
                 }
             } finally {
                 mLocalDictionaryController.unlock();
             }
         }
+        return null;
     }
 
     @Override
@@ -306,7 +305,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
         // Build the new binary dictionary
         final BinaryDictionary newBinaryDictionary =
                 new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */,
-                        null);
+                        null, mDictType);
 
         if (mBinaryDictionary != null) {
             // Ensure all threads accessing the current dictionary have finished before swapping in
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index f5886aa12802b9ba5e9c1da3af8a1eaa283f670e..76213c0dabae550f6ded701952f03c647945d392 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -38,7 +38,6 @@ public class ExpandableDictionary extends Dictionary {
 
     private Context mContext;
     private char[] mWordBuilder = new char[BinaryDictionary.MAX_WORD_LENGTH];
-    private int mDicTypeId;
     private int mMaxDepth;
     private int mInputLength;
 
@@ -152,11 +151,11 @@ public class ExpandableDictionary extends Dictionary {
 
     private int[][] mCodes;
 
-    public ExpandableDictionary(Context context, int dicTypeId) {
+    public ExpandableDictionary(final Context context, final String dictType) {
+        super(dictType);
         mContext = context;
         clearDictionary();
         mCodes = new int[BinaryDictionary.MAX_WORD_LENGTH][];
-        mDicTypeId = dicTypeId;
     }
 
     public void loadDictionary() {
@@ -248,20 +247,20 @@ public class ExpandableDictionary extends Dictionary {
     }
 
     @Override
-    public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
-            final WordCallback callback, final ProximityInfo proximityInfo) {
+    public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
         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;
+            if (mUpdatingDictionary) return null;
         }
         if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) {
-            return;
+            return null;
         }
         final ArrayList<SuggestedWordInfo> suggestions =
                 getWordsInner(codes, prevWordForBigrams, proximityInfo);
-        Utils.addAllSuggestions(mDicTypeId, Dictionary.UNIGRAM, suggestions, callback);
+        return suggestions;
     }
 
     protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
@@ -269,8 +268,9 @@ public class ExpandableDictionary extends Dictionary {
         final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
         mInputLength = codes.size();
         if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
-        final int[] xCoordinates = codes.getXCoordinates();
-        final int[] yCoordinates = codes.getYCoordinates();
+        final InputPointers ips = codes.getInputPointers();
+        final int[] xCoordinates = ips.getXCoordinates();
+        final int[] yCoordinates = ips.getYCoordinates();
         // Cache the codes so that we don't have to lookup an array list
         for (int i = 0; i < mInputLength; i++) {
             // TODO: Calculate proximity info here.
@@ -383,7 +383,7 @@ public class ExpandableDictionary extends Dictionary {
             // the respective size of the typed word and the suggestion if it matters sometime
             // in the future.
             suggestions.add(new SuggestedWordInfo(new String(word, 0, depth + 1), finalFreq,
-                    SuggestedWordInfo.KIND_CORRECTION));
+                    SuggestedWordInfo.KIND_CORRECTION, mDictType));
             if (suggestions.size() >= Suggest.MAX_SUGGESTIONS) return false;
         }
         if (null != node.mShortcutTargets) {
@@ -391,7 +391,7 @@ public class ExpandableDictionary extends Dictionary {
             for (int shortcutIndex = 0; shortcutIndex < length; ++shortcutIndex) {
                 final char[] shortcut = node.mShortcutTargets.get(shortcutIndex);
                 suggestions.add(new SuggestedWordInfo(new String(shortcut, 0, shortcut.length),
-                        finalFreq, SuggestedWordInfo.KIND_SHORTCUT));
+                        finalFreq, SuggestedWordInfo.KIND_SHORTCUT, mDictType));
                 if (suggestions.size() > Suggest.MAX_SUGGESTIONS) return false;
             }
         }
@@ -600,22 +600,25 @@ public class ExpandableDictionary extends Dictionary {
     }
 
     private void runBigramReverseLookUp(final CharSequence previousWord,
-            final WordCallback callback) {
+            final ArrayList<SuggestedWordInfo> suggestions) {
         // Search for the lowercase version of the word only, because that's where bigrams
         // store their sons.
         Node prevWord = searchNode(mRoots, previousWord.toString().toLowerCase(), 0,
                 previousWord.length());
         if (prevWord != null && prevWord.mNGrams != null) {
-            reverseLookUp(prevWord.mNGrams, callback);
+            reverseLookUp(prevWord.mNGrams, suggestions);
         }
     }
 
     @Override
-    public void getBigrams(final WordComposer codes, final CharSequence previousWord,
-            final WordCallback callback) {
+    public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+            final CharSequence previousWord) {
         if (!reloadDictionaryIfRequired()) {
-            runBigramReverseLookUp(previousWord, callback);
+            final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
+            runBigramReverseLookUp(previousWord, suggestions);
+            return suggestions;
         }
+        return null;
     }
 
     /**
@@ -642,11 +645,12 @@ public class ExpandableDictionary extends Dictionary {
 
     /**
      * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words
-     * through callback.
+     * to the suggestions list passed as an argument.
      * @param terminalNodes list of terminal nodes we want to add
+     * @param suggestions the suggestion collection to add the word to
      */
     private void reverseLookUp(LinkedList<NextWord> terminalNodes,
-            final WordCallback callback) {
+            final ArrayList<SuggestedWordInfo> suggestions) {
         Node node;
         int freq;
         for (NextWord nextWord : terminalNodes) {
@@ -660,8 +664,9 @@ public class ExpandableDictionary extends Dictionary {
             } while (node != null);
 
             if (freq >= 0) {
-                callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index,
-                        freq, mDicTypeId, Dictionary.BIGRAM);
+                suggestions.add(new SuggestedWordInfo(new String(mLookedUpString, index,
+                        BinaryDictionary.MAX_WORD_LENGTH - index),
+                        freq, SuggestedWordInfo.KIND_CORRECTION, mDictType));
             }
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java
new file mode 100644
index 0000000000000000000000000000000000000000..218243e9ff78c634f16d45b91891b77d4752f8ab
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/InputPointers.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import java.util.Arrays;
+
+public class InputPointers {
+    private final ScalableIntArray mXCoordinates = new ScalableIntArray();
+    private final ScalableIntArray mYCoordinates = new ScalableIntArray();
+    private final ScalableIntArray mPointerIds = new ScalableIntArray();
+    private final ScalableIntArray mTimes = new ScalableIntArray();
+
+    public void addPointer(int index, int x, int y, int pointerId, int time) {
+        mXCoordinates.add(index, x);
+        mYCoordinates.add(index, y);
+        mPointerIds.add(index, pointerId);
+        mTimes.add(index, time);
+    }
+
+    public void addPointer(int x, int y, int pointerId, int time) {
+        mXCoordinates.add(x);
+        mYCoordinates.add(y);
+        mPointerIds.add(pointerId);
+        mTimes.add(time);
+    }
+
+    public void set(InputPointers ip) {
+        mXCoordinates.set(ip.mXCoordinates);
+        mYCoordinates.set(ip.mYCoordinates);
+        mPointerIds.set(ip.mPointerIds);
+        mTimes.set(ip.mTimes);
+    }
+
+    public void copy(InputPointers ip) {
+        mXCoordinates.copy(ip.mXCoordinates);
+        mYCoordinates.copy(ip.mYCoordinates);
+        mPointerIds.copy(ip.mPointerIds);
+        mTimes.copy(ip.mTimes);
+    }
+
+    public void reset() {
+        mXCoordinates.reset();
+        mYCoordinates.reset();
+        mPointerIds.reset();
+        mTimes.reset();
+    }
+
+    public int getPointerSize() {
+        return mXCoordinates.getLength();
+    }
+
+    public int[] getXCoordinates() {
+        return mXCoordinates.mArray;
+    }
+
+    public int[] getYCoordinates() {
+        return mYCoordinates.mArray;
+    }
+
+    public int[] getPointerIds() {
+        return mPointerIds.mArray;
+    }
+
+    public int[] getTimes() {
+        return mTimes.mArray;
+    }
+
+    private static class ScalableIntArray {
+        private static final int DEFAULT_SIZE = BinaryDictionary.MAX_WORD_LENGTH;
+        private int[] mArray;
+        private int mLength;
+
+        public ScalableIntArray() {
+            reset();
+        }
+
+        public void add(int index, int val) {
+            if (mLength < index + 1) {
+                mLength = index;
+                add(val);
+            } else {
+                mArray[index] = val;
+            }
+        }
+
+        public void add(int val) {
+            if (mLength >= mArray.length) {
+                final int[] newArray = new int[mLength * 2];
+                System.arraycopy(mArray, 0, newArray, 0, mLength);
+            }
+            mArray[mLength] = val;
+            ++mLength;
+        }
+
+        public int getLength() {
+            return mLength;
+        }
+
+        public void reset() {
+            mArray = new int[DEFAULT_SIZE];
+            mLength = 0;
+        }
+
+        public int[] getPrimitiveArray() {
+            return mArray;
+        }
+
+        public void copy(ScalableIntArray ip) {
+            mArray = Arrays.copyOf(ip.mArray, ip.mArray.length);
+        }
+
+        public void set(ScalableIntArray ip) {
+            mArray = ip.mArray;
+            mLength = ip.mLength;
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index 4e1f5fe9218ae4fadb18290b9c21f0804d17e37b..318aecb5038bbd6738ac196bb8dd13bb49a2deb1 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -41,26 +41,26 @@ public class LastComposedWord {
     public static final int NOT_A_SEPARATOR = -1;
 
     public final int[] mPrimaryKeyCodes;
-    public final int[] mXCoordinates;
-    public final int[] mYCoordinates;
     public final String mTypedWord;
     public final String mCommittedWord;
     public final int mSeparatorCode;
     public final CharSequence mPrevWord;
+    public final InputPointers mInputPointers = new InputPointers();
 
     private boolean mActive;
 
     public static final LastComposedWord NOT_A_COMPOSED_WORD =
-            new LastComposedWord(null, null, null, "", "", NOT_A_SEPARATOR, null);
+            new LastComposedWord(null, null, "", "", NOT_A_SEPARATOR, null);
 
     // Warning: this is using the passed objects as is and fully expects them to be
     // immutable. Do not fiddle with their contents after you passed them to this constructor.
-    public LastComposedWord(final int[] primaryKeyCodes, final int[] xCoordinates,
-            final int[] yCoordinates, final String typedWord, final String committedWord,
+    public LastComposedWord(final int[] primaryKeyCodes, final InputPointers inputPointers,
+            final String typedWord, final String committedWord,
             final int separatorCode, final CharSequence prevWord) {
         mPrimaryKeyCodes = primaryKeyCodes;
-        mXCoordinates = xCoordinates;
-        mYCoordinates = yCoordinates;
+        if (inputPointers != null) {
+            mInputPointers.copy(inputPointers);
+        }
         mTypedWord = typedWord;
         mCommittedWord = committedWord;
         mSeparatorCode = separatorCode;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 5cbf40400fda3c758f373906f8bf07eae2a112f7..21f0ea0077f495657749223de58d7731e3bbab75 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -471,8 +471,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
         // is not guaranteed. It may even be called at the same time on a different thread.
         if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
-        mUserHistoryDictionary = UserHistoryDictionary.getInstance(
-                this, localeStr, Suggest.DIC_USER_HISTORY, mPrefs);
+        mUserHistoryDictionary = UserHistoryDictionary.getInstance(this, localeStr, mPrefs);
         mSuggest.setUserHistoryDictionary(mUserHistoryDictionary);
     }
 
@@ -500,8 +499,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                     // If the locale has changed then recreate the contacts dictionary. This
                     // allows locale dependent rules for handling bigram name predictions.
                     oldContactsDictionary.close();
-                    dictionaryToUse = new ContactsBinaryDictionary(
-                        this, Suggest.DIC_CONTACTS, locale);
+                    dictionaryToUse = new ContactsBinaryDictionary(this, locale);
                 } else {
                     // Make sure the old contacts dictionary is opened. If it is already open,
                     // this is a no-op, so it's safe to call it anyways.
@@ -509,7 +507,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                     dictionaryToUse = oldContactsDictionary;
                 }
             } else {
-                dictionaryToUse = new ContactsBinaryDictionary(this, Suggest.DIC_CONTACTS, locale);
+                dictionaryToUse = new ContactsBinaryDictionary(this, locale);
             }
         }
 
@@ -890,7 +888,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                 applicationSuggestedWords,
                 false /* typedWordValid */,
                 false /* hasAutoCorrectionCandidate */,
-                false /* allowsToBeAutoCorrected */,
                 false /* isPunctuationSuggestions */,
                 false /* isObsoleteSuggestions */,
                 false /* isPrediction */);
@@ -1718,9 +1715,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             return;
         }
 
-        mHandler.cancelUpdateSuggestions();
-        mHandler.cancelUpdateBigramPredictions();
-
         if (!mWordComposer.isComposingWord()) {
             // We are never called with an empty word composer, but if because of a bug
             // we are, what we should do here is just call updateBigramsPredictions. This will
@@ -1736,7 +1730,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         // getSuggestedWords handles gracefully a null value of prevWord
         final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
                 prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
-                mCurrentSettings.mCorrectionEnabled);
+                mCurrentSettings.mCorrectionEnabled, false);
 
         // Basically, we update the suggestion strip only when suggestion count > 1.  However,
         // there is an exception: We update the suggestion strip whenever typed word's length
@@ -1745,7 +1739,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         // need to clear the previous state when the user starts typing a word (i.e. typed word's
         // length == 1).
         if (suggestedWords.size() > 1 || typedWord.length() == 1
-                || !suggestedWords.mAllowsToBeAutoCorrected
+                || !suggestedWords.mTypedWordValid
                 || mSuggestionsView.isShowingAddToDictionaryHint()) {
             showSuggestions(suggestedWords, typedWord);
         } else {
@@ -1760,7 +1754,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                     new SuggestedWords(typedWordAndPreviousSuggestions,
                             false /* typedWordValid */,
                             false /* hasAutoCorrectionCandidate */,
-                            false /* allowsToBeAutoCorrected */,
                             false /* isPunctuationSuggestions */,
                             true /* isObsoleteSuggestions */,
                             false /* isPrediction */);
@@ -1771,7 +1764,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) {
         final CharSequence autoCorrection;
         if (suggestedWords.size() > 0) {
-            if (suggestedWords.hasAutoCorrectionWord()) {
+            if (suggestedWords.mWillAutoCorrect) {
                 autoCorrection = suggestedWords.getWord(1);
             } else {
                 autoCorrection = typedWord;
@@ -1936,8 +1929,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     }
 
     public void updateBigramPredictions() {
-        if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation))
+        mHandler.cancelUpdateSuggestions();
+        mHandler.cancelUpdateBigramPredictions();
+
+        if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+            if (mWordComposer.isComposingWord()) {
+                Log.w(TAG, "Called updateBigramPredictions but suggestions were not requested!");
+                mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
+            }
             return;
+        }
 
         if (!mCurrentSettings.mBigramPredictionEnabled) {
             setPunctuationSuggestions();
@@ -1948,7 +1949,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         if (mCurrentSettings.mCorrectionEnabled) {
             final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators);
             if (!TextUtils.isEmpty(prevWord)) {
-                suggestedWords = mSuggest.getBigramPredictions(prevWord);
+                suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
+                        prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
+                        mCurrentSettings.mCorrectionEnabled, true);
             } else {
                 suggestedWords = null;
             }
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index dc0868e7c38e8f4a25f1f3d1b81e0b9441c9efa2..e843848bc5ac85ef0040e89f4dd02fcedebfa8c0 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -71,7 +71,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
     public static void onStartSuggestion(CharSequence previousWords) {
     }
 
-    public static void onAddSuggestedWord(String word, int typeId, int dataType) {
+    public static void onAddSuggestedWord(String word, String sourceDictionaryId) {
     }
 
     public static void onSetKeyboard(Keyboard kb) {
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index cf3cc78732fbc10cb3d5e3239ef1f859136256e5..e83d7c84a1188de663708f901b35a88f4805b7fd 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -197,6 +197,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
         Log.d(TAG, "stop called");
         if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
             mLoggingState = LOGGING_STATE_STOPPING;
+            flushEventQueue(true);
             // put this in the Handler queue so pending writes are processed first.
             mLoggingHandler.post(new Runnable() {
                 @Override
@@ -379,11 +380,52 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
         mCurrentLogUnit.addLogAtom(keys, values, false);
     }
 
+    // Used to track how often words are logged.  Too-frequent logging can leak
+    // semantics, disclosing private data.
+    /* package for test */ static class LoggingFrequencyState {
+        private static final int DEFAULT_WORD_LOG_FREQUENCY = 10;
+        private int mWordsRemainingToSkip;
+        private final int mFrequency;
+
+        /**
+         * Tracks how often words may be uploaded.
+         *
+         * @param frequency 1=Every word, 2=Every other word, etc.
+         */
+        public LoggingFrequencyState(int frequency) {
+            mFrequency = frequency;
+            mWordsRemainingToSkip = mFrequency;
+        }
+
+        public void onWordLogged() {
+            mWordsRemainingToSkip = mFrequency;
+        }
+
+        public void onWordNotLogged() {
+            if (mWordsRemainingToSkip > 1) {
+                mWordsRemainingToSkip--;
+            }
+        }
+
+        public boolean isSafeToLog() {
+            return mWordsRemainingToSkip <= 1;
+        }
+    }
+
+    /* package for test */ LoggingFrequencyState mLoggingFrequencyState =
+            new LoggingFrequencyState(LoggingFrequencyState.DEFAULT_WORD_LOG_FREQUENCY);
+
     /* package for test */ boolean isPrivacyThreat(String word) {
-        // currently: word not in dictionary or contains numbers.
+        // Current checks:
+        // - Word not in dictionary
+        // - Word contains numbers
+        // - Privacy-safe word not logged recently
         if (TextUtils.isEmpty(word)) {
             return false;
         }
+        if (!mLoggingFrequencyState.isSafeToLog()) {
+            return true;
+        }
         final int length = word.length();
         boolean hasLetter = false;
         for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
@@ -410,15 +452,26 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
         return false;
     }
 
+    private void onWordComplete(String word) {
+        final boolean isPrivacyThreat = isPrivacyThreat(word);
+        flushEventQueue(isPrivacyThreat);
+        if (isPrivacyThreat) {
+            mLoggingFrequencyState.onWordNotLogged();
+        } else {
+            mLoggingFrequencyState.onWordLogged();
+        }
+    }
+
     /**
      * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events.
      */
-    /* package for test */ synchronized void flushQueue(boolean removePotentiallyPrivateEvents) {
+    /* package for test */ synchronized void flushEventQueue(
+            boolean removePotentiallyPrivateEvents) {
         if (isAllowedToLog()) {
             mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents);
             mLoggingHandler.post(mCurrentLogUnit);
-            mCurrentLogUnit = new LogUnit();
         }
+        mCurrentLogUnit = new LogUnit();
     }
 
     private synchronized void outputEvent(final String[] keys, final Object[] values) {
@@ -479,12 +532,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
                     SuggestedWords words = (SuggestedWords) value;
                     mJsonWriter.beginObject();
                     mJsonWriter.name("typedWordValid").value(words.mTypedWordValid);
-                    mJsonWriter.name("hasAutoCorrectionCandidate")
-                        .value(words.mHasAutoCorrectionCandidate);
+                    mJsonWriter.name("willAutoCorrect").value(words.mWillAutoCorrect);
                     mJsonWriter.name("isPunctuationSuggestions")
                         .value(words.mIsPunctuationSuggestions);
-                    mJsonWriter.name("allowsToBeAutoCorrected")
-                        .value(words.mAllowsToBeAutoCorrected);
                     mJsonWriter.name("isObsoleteSuggestions")
                         .value(words.mIsObsoleteSuggestions);
                     mJsonWriter.name("isPrediction")
@@ -652,7 +702,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
         final ResearchLogger researchLogger = getInstance();
         researchLogger.enqueuePotentiallyPrivateEvent(
                 EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values);
-        researchLogger.flushQueue(researchLogger.isPrivacyThreat(autoCorrection));
     }
 
     private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = {
@@ -665,7 +714,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
         };
         final ResearchLogger researchLogger = getInstance();
         researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values);
-        researchLogger.flushQueue(researchLogger.isPrivacyThreat(scrubbedWord));
+        researchLogger.onWordComplete(scrubbedWord);
     }
 
     private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = {
@@ -743,7 +792,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
             }
             final ResearchLogger researchLogger = getInstance();
             researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values);
-            researchLogger.flushQueue(true); // Play it safe.  Remove privacy-sensitive events.
+            researchLogger.flushEventQueue(true); // Play it safe.  Remove privacy-sensitive events.
         }
     }
 
@@ -824,7 +873,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
         final ResearchLogger researchLogger = getInstance();
         researchLogger.enqueuePotentiallyPrivateEvent(
                 EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values);
-        researchLogger.flushQueue(researchLogger.isPrivacyThreat(cs.toString()));
     }
 
     private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = {
@@ -839,7 +887,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
         final ResearchLogger researchLogger = getInstance();
         researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY,
                 values);
-        researchLogger.flushQueue(researchLogger.isPrivacyThreat(suggestion.toString()));
     }
 
     private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = {
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 0c19bed0572be4f9164344cb0a84337b5ee44384..40d327ebb62ec29e7fcbcfb7d7a0853c4c958aec 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -340,13 +340,6 @@ public class RichInputConnection {
      * Returns the word before the cursor if the cursor is at the end of a word, null otherwise
      */
     public CharSequence getWordBeforeCursorIfAtEndOfWord(final SettingsValues settings) {
-        // Bail out if the cursor is not at the end of a word (cursor must be preceded by
-        // non-whitespace, non-separator, non-start-of-text)
-        // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
-        final CharSequence textBeforeCursor = getTextBeforeCursor(1, 0);
-        if (TextUtils.isEmpty(textBeforeCursor)
-                || settings.isWordSeparator(textBeforeCursor.charAt(0))) return null;
-
         // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
         // separator or end of line/text)
         // Example: "test|"<EOL> "te|st" get rejected here
@@ -363,6 +356,15 @@ public class RichInputConnection {
             word = word.subSequence(1, word.length());
         }
         if (TextUtils.isEmpty(word)) return null;
+        // Find the last code point of the string
+        final int lastCodePoint = Character.codePointBefore(word, word.length());
+        // If for some reason the text field contains non-unicode binary data, or if the
+        // charsequence is exactly one char long and the contents is a low surrogate, return null.
+        if (!Character.isDefined(lastCodePoint)) return null;
+        // Bail out if the cursor is not at the end of a word (cursor must be preceded by
+        // non-whitespace, non-separator, non-start-of-text)
+        // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
+        if (settings.isWordSeparator(lastCodePoint)) return null;
         final char firstChar = word.charAt(0); // we just tested that word is not empty
         if (word.length() == 1 && !Character.isLetter(firstChar)) return null;
 
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 4c67b4957fb4bf7a15ca70b687b47139b2872bc1..4c89a6e91474c7aeab9c8c83f293e5fd3f57d8e4 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -143,19 +143,39 @@ public class Settings extends InputMethodSettingsFragment
             generalSettings.removePreference(mVoicePreference);
         }
 
+        final PreferenceGroup advancedSettings =
+                (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS);
         if (!VibratorUtils.getInstance(context).hasVibrator()) {
-            final PreferenceGroup advancedSettings =
-                    (PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS);
             generalSettings.removePreference(findPreference(PREF_VIBRATE_ON));
             if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
                 advancedSettings.removePreference(findPreference(PREF_VIBRATION_DURATION_SETTINGS));
             }
         }
 
-        final boolean showPopupOption = res.getBoolean(
+        final boolean showKeyPreviewPopupOption = res.getBoolean(
                 R.bool.config_enable_show_popup_on_keypress_option);
-        if (!showPopupOption) {
+        mKeyPreviewPopupDismissDelay =
+                (ListPreference) findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+        if (!showKeyPreviewPopupOption) {
             generalSettings.removePreference(findPreference(PREF_POPUP_ON));
+            if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
+                advancedSettings.removePreference(mKeyPreviewPopupDismissDelay);
+            }
+        } else {
+            final String[] entries = new String[] {
+                    res.getString(R.string.key_preview_popup_dismiss_no_delay),
+                    res.getString(R.string.key_preview_popup_dismiss_default_delay),
+            };
+            final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
+                    R.integer.config_key_preview_linger_timeout));
+            mKeyPreviewPopupDismissDelay.setEntries(entries);
+            mKeyPreviewPopupDismissDelay.setEntryValues(
+                    new String[] { "0", popupDismissDelayDefaultValue });
+            if (null == mKeyPreviewPopupDismissDelay.getValue()) {
+                mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
+            }
+            mKeyPreviewPopupDismissDelay.setEnabled(
+                    SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
         }
 
         final CheckBoxPreference includeOtherImesInLanguageSwitchList =
@@ -163,23 +183,6 @@ public class Settings extends InputMethodSettingsFragment
         includeOtherImesInLanguageSwitchList.setEnabled(
                 !SettingsValues.isLanguageSwitchKeySupressed(prefs));
 
-        mKeyPreviewPopupDismissDelay =
-                (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
-        final String[] entries = new String[] {
-                res.getString(R.string.key_preview_popup_dismiss_no_delay),
-                res.getString(R.string.key_preview_popup_dismiss_default_delay),
-        };
-        final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
-                R.integer.config_key_preview_linger_timeout));
-        mKeyPreviewPopupDismissDelay.setEntries(entries);
-        mKeyPreviewPopupDismissDelay.setEntryValues(
-                new String[] { "0", popupDismissDelayDefaultValue });
-        if (null == mKeyPreviewPopupDismissDelay.getValue()) {
-            mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
-        }
-        mKeyPreviewPopupDismissDelay.setEnabled(
-                SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
-
         final PreferenceScreen dictionaryLink =
                 (PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
         final Intent intent = dictionaryLink.getIntent();
@@ -305,13 +308,15 @@ public class Settings extends InputMethodSettingsFragment
 
     private void updateKeyPreviewPopupDelaySummary() {
         final ListPreference lp = mKeyPreviewPopupDismissDelay;
-        lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]);
+        final CharSequence[] entries = lp.getEntries();
+        if (entries == null || entries.length <= 0) return;
+        lp.setSummary(entries[lp.findIndexOfValue(lp.getValue())]);
     }
 
     private void updateVoiceModeSummary() {
         mVoicePreference.setSummary(
                 getResources().getStringArray(R.array.voice_input_modes_summary)
-                [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
+                        [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
     }
 
     private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index ef423f19b525ce2b35a2b06cd1cb18b4c2dd5265..aab84fccddad301b6fbb434cbacad553384c970f 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -179,13 +179,13 @@ public class SettingsValues {
         if (puncs != null) {
             for (final String puncSpec : puncs) {
                 puncList.add(new SuggestedWordInfo(KeySpecParser.getLabel(puncSpec),
-                        SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED));
+                        SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED,
+                        Dictionary.TYPE_HARDCODED));
             }
         }
         return new SuggestedWords(puncList,
                 false /* typedWordValid */,
                 false /* hasAutoCorrectionCandidate */,
-                false /* allowsToBeAutoCorrected */,
                 true /* isPunctuationSuggestions */,
                 false /* isObsoleteSuggestions */,
                 false /* isPrediction */);
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index a43b90525f2f9f798b0bef34c34d93edebf7947c..6e7d985d62fbc097a6ab49111f23c21633bfd1c3 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -184,6 +184,9 @@ public class StringUtils {
         final char[] characters = string.toCharArray();
         final int length = characters.length;
         final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
+        if (length <= 0) {
+            return new int[0];
+        }
         int codePoint = Character.codePointAt(characters, 0);
         int dsti = 0;
         for (int srci = Character.charCount(codePoint);
diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
index ca293060aee079062c34a55c3ef0bdf1e3d71404..acc17ef3f04fcd223d6f857c6d641a8ddbb999f6 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java
@@ -60,6 +60,10 @@ public class SubtypeLocale {
     // Exceptional locales to display name map.
     private static final HashMap<String, String> sExceptionalDisplayNamesMap =
             new HashMap<String, String>();
+    // Keyboard layout set name for the subtypes that don't have a keyboardLayoutSet extra value.
+    // This is for compatibility to keep the same subtype ids as pre-JellyBean.
+    private static final HashMap<String,String> sLocaleAndExtraValueToKeyboardLayoutSetMap =
+            new HashMap<String,String>();
 
     private SubtypeLocale() {
         // Intentional empty constructor for utility class.
@@ -97,6 +101,14 @@ public class SubtypeLocale {
             final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
             sExceptionalLocaleToWithLayoutNameIdsMap.put(localeString, resId);
         }
+
+        final String[] keyboardLayoutSetMap = res.getStringArray(
+                R.array.locale_and_extra_value_to_keyboard_layout_set_map);
+        for (int i = 0; i < keyboardLayoutSetMap.length; i += 2) {
+            final String key = keyboardLayoutSetMap[i];
+            final String keyboardLayoutSet = keyboardLayoutSetMap[i + 1];
+            sLocaleAndExtraValueToKeyboardLayoutSetMap.put(key, keyboardLayoutSet);
+        }
     }
 
     public static String[] getPredefinedKeyboardLayoutSet() {
@@ -193,7 +205,14 @@ public class SubtypeLocale {
     }
 
     public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) {
-        final String keyboardLayoutSet = subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET);
+        String keyboardLayoutSet = subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET);
+        if (keyboardLayoutSet == null) {
+            // This subtype doesn't have a keyboardLayoutSet extra value, so lookup its keyboard
+            // layout set in sLocaleAndExtraValueToKeyboardLayoutSetMap to keep it compatible with
+            // pre-JellyBean.
+            final String key = subtype.getLocale() + ":" + subtype.getExtraValue();
+            keyboardLayoutSet = sLocaleAndExtraValueToKeyboardLayoutSetMap.get(key);
+        }
         // TODO: Remove this null check when InputMethodManager.getCurrentInputMethodSubtype is
         // fixed.
         if (keyboardLayoutSet == null) {
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 5aecc13717cf2214c1b1bea2467ce3fa7af2946f..f810eccf487fc5a7f0ddc0695975c8e93f44c5e0 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -18,7 +18,6 @@ package com.android.inputmethod.latin;
 
 import android.content.Context;
 import android.text.TextUtils;
-import android.util.Log;
 
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.ProximityInfo;
@@ -26,6 +25,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.concurrent.ConcurrentHashMap;
@@ -34,80 +34,47 @@ import java.util.concurrent.ConcurrentHashMap;
  * This class loads a dictionary and provides a list of suggestions for a given sequence of
  * characters. This includes corrections and completions.
  */
-public class Suggest implements Dictionary.WordCallback {
+public class Suggest {
     public static final String TAG = Suggest.class.getSimpleName();
 
-    public static final int APPROX_MAX_WORD_LENGTH = 32;
-
     // TODO: rename this to CORRECTION_OFF
     public static final int CORRECTION_NONE = 0;
     // TODO: rename this to CORRECTION_ON
     public static final int CORRECTION_FULL = 1;
 
-    // It seems the following values are only used for logging.
-    public static final int DIC_USER_TYPED = 0;
-    public static final int DIC_MAIN = 1;
-    public static final int DIC_USER = 2;
-    public static final int DIC_USER_HISTORY = 3;
-    public static final int DIC_CONTACTS = 4;
-    public static final int DIC_WHITELIST = 6;
-    // If you add a type of dictionary, increment DIC_TYPE_LAST_ID
-    // TODO: this value seems unused. Remove it?
-    public static final int DIC_TYPE_LAST_ID = 6;
-    public static final String DICT_KEY_MAIN = "main";
-    public static final String DICT_KEY_CONTACTS = "contacts";
-    // User dictionary, the system-managed one.
-    public static final String DICT_KEY_USER = "user";
-    // User history dictionary for the unigram map, internal to LatinIME
-    public static final String DICT_KEY_USER_HISTORY_UNIGRAM = "history_unigram";
-    // User history dictionary for the bigram map, internal to LatinIME
-    public static final String DICT_KEY_USER_HISTORY_BIGRAM = "history_bigram";
-    public static final String DICT_KEY_WHITELIST ="whitelist";
-
     private static final boolean DBG = LatinImeLogger.sDBG;
 
     private Dictionary mMainDictionary;
     private ContactsBinaryDictionary mContactsDict;
     private WhitelistDictionary mWhiteListDictionary;
-    private final ConcurrentHashMap<String, Dictionary> mUnigramDictionaries =
-            new ConcurrentHashMap<String, Dictionary>();
-    private final ConcurrentHashMap<String, Dictionary> mBigramDictionaries =
+    private final ConcurrentHashMap<String, Dictionary> mDictionaries =
             new ConcurrentHashMap<String, Dictionary>();
 
     public static final int MAX_SUGGESTIONS = 18;
 
-    private static final int PREF_MAX_BIGRAMS = 60;
-
     private float mAutoCorrectionThreshold;
 
-    private ArrayList<SuggestedWordInfo> mSuggestions = new ArrayList<SuggestedWordInfo>();
-    private ArrayList<SuggestedWordInfo> mBigramSuggestions = new ArrayList<SuggestedWordInfo>();
-    private CharSequence mConsideredWord;
-
-    // TODO: Remove these member variables by passing more context to addWord() callback method
-    private boolean mIsFirstCharCapitalized;
-    private boolean mIsAllUpperCase;
-    private int mTrailingSingleQuotesCount;
-
-    private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
+    // Locale used for upper- and title-casing words
+    final private Locale mLocale;
 
     public Suggest(final Context context, final Locale locale) {
         initAsynchronously(context, locale);
+        mLocale = locale;
     }
 
     /* package for test */ Suggest(final Context context, final File dictionary,
             final long startOffset, final long length, final Locale locale) {
         final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary,
                 startOffset, length /* useFullEditDistance */, false, locale);
+        mLocale = locale;
         mMainDictionary = mainDict;
-        addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict);
-        addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict);
+        addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, mainDict);
         initWhitelistAndAutocorrectAndPool(context, locale);
     }
 
     private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) {
         mWhiteListDictionary = new WhitelistDictionary(context, locale);
-        addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
+        addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_WHITELIST, mWhiteListDictionary);
     }
 
     private void initAsynchronously(final Context context, final Locale locale) {
@@ -136,8 +103,7 @@ public class Suggest implements Dictionary.WordCallback {
             public void run() {
                 final DictionaryCollection newMainDict =
                         DictionaryFactory.createMainDictionaryFromManager(context, locale);
-                addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict);
-                addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict);
+                addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, newMainDict);
                 mMainDictionary = newMainDict;
             }
         }.start();
@@ -158,11 +124,7 @@ public class Suggest implements Dictionary.WordCallback {
     }
 
     public ConcurrentHashMap<String, Dictionary> getUnigramDictionaries() {
-        return mUnigramDictionaries;
-    }
-
-    public static int getApproxMaxWordLength() {
-        return APPROX_MAX_WORD_LENGTH;
+        return mDictionaries;
     }
 
     /**
@@ -170,7 +132,7 @@ public class Suggest implements Dictionary.WordCallback {
      * before the main dictionary, if set. This refers to the system-managed user dictionary.
      */
     public void setUserDictionary(UserBinaryDictionary userDictionary) {
-        addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER, userDictionary);
+        addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER, userDictionary);
     }
 
     /**
@@ -180,213 +142,147 @@ public class Suggest implements Dictionary.WordCallback {
      */
     public void setContactsDictionary(ContactsBinaryDictionary contactsDictionary) {
         mContactsDict = contactsDictionary;
-        addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
-        addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
+        addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_CONTACTS, contactsDictionary);
     }
 
     public void setUserHistoryDictionary(UserHistoryDictionary userHistoryDictionary) {
-        addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER_HISTORY_UNIGRAM,
-                userHistoryDictionary);
-        addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_HISTORY_BIGRAM,
-                userHistoryDictionary);
+        addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER_HISTORY, userHistoryDictionary);
     }
 
     public void setAutoCorrectionThreshold(float threshold) {
         mAutoCorrectionThreshold = threshold;
     }
 
-    private static CharSequence capitalizeWord(final boolean all, final boolean first,
-            final CharSequence word) {
-        if (TextUtils.isEmpty(word) || !(all || first)) return word;
-        final int wordLength = word.length();
-        final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
-        // TODO: Must pay attention to locale when changing case.
-        if (all) {
-            sb.append(word.toString().toUpperCase());
-        } else if (first) {
-            sb.append(Character.toUpperCase(word.charAt(0)));
-            if (wordLength > 1) {
-                sb.append(word.subSequence(1, wordLength));
-            }
-        }
-        return sb;
-    }
-
-    protected void addBigramToSuggestions(SuggestedWordInfo bigram) {
-        mSuggestions.add(bigram);
-    }
-
-    private static final WordComposer sEmptyWordComposer = new WordComposer();
-    public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) {
-        LatinImeLogger.onStartSuggestion(prevWordForBigram);
-        mIsFirstCharCapitalized = false;
-        mIsAllUpperCase = false;
-        mTrailingSingleQuotesCount = 0;
-        mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
-
-        // Treating USER_TYPED as UNIGRAM suggestion for logging now.
-        LatinImeLogger.onAddSuggestedWord("", Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
-        mConsideredWord = "";
-
-        mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
-
-        getAllBigrams(prevWordForBigram, sEmptyWordComposer);
-
-        // Nothing entered: return all bigrams for the previous word
-        int insertCount = Math.min(mBigramSuggestions.size(), MAX_SUGGESTIONS);
-        for (int i = 0; i < insertCount; ++i) {
-            addBigramToSuggestions(mBigramSuggestions.get(i));
-        }
-
-        SuggestedWordInfo.removeDups(mSuggestions);
-
-        return new SuggestedWords(mSuggestions,
-                false /* typedWordValid */,
-                false /* hasAutoCorrectionCandidate */,
-                false /* allowsToBeAutoCorrected */,
-                false /* isPunctuationSuggestions */,
-                false /* isObsoleteSuggestions */,
-                true /* isPrediction */);
-    }
-
     // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
     public SuggestedWords getSuggestedWords(
             final WordComposer wordComposer, CharSequence prevWordForBigram,
-            final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) {
+            final ProximityInfo proximityInfo, final boolean isCorrectionEnabled,
+            // TODO: remove isPrediction parameter. It effectively means the same thing
+            // as wordComposer.size() <= 1
+            final boolean isPrediction) {
         LatinImeLogger.onStartSuggestion(prevWordForBigram);
-        mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
-        mIsAllUpperCase = wordComposer.isAllUpperCase();
-        mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
-        mSuggestions = new ArrayList<SuggestedWordInfo>(MAX_SUGGESTIONS);
+        final boolean isFirstCharCapitalized =
+                !isPrediction && wordComposer.isFirstCharCapitalized();
+        final boolean isAllUpperCase = !isPrediction && wordComposer.isAllUpperCase();
+        final int trailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
+        final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator,
+                MAX_SUGGESTIONS);
 
         final String typedWord = wordComposer.getTypedWord();
-        final String consideredWord = mTrailingSingleQuotesCount > 0
-                ? typedWord.substring(0, typedWord.length() - mTrailingSingleQuotesCount)
+        final String consideredWord = trailingSingleQuotesCount > 0
+                ? typedWord.substring(0, typedWord.length() - trailingSingleQuotesCount)
                 : typedWord;
-        // Treating USER_TYPED as UNIGRAM suggestion for logging now.
-        LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
-        mConsideredWord = consideredWord;
+        LatinImeLogger.onAddSuggestedWord(typedWord, Dictionary.TYPE_USER_TYPED);
 
         if (wordComposer.size() <= 1 && isCorrectionEnabled) {
             // At first character typed, search only the bigrams
-            mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
-
             if (!TextUtils.isEmpty(prevWordForBigram)) {
                 for (final String key : mDictionaries.keySet()) {
                     final Dictionary dictionary = mDictionaries.get(key);
                     suggestionsSet.addAll(dictionary.getBigrams(wordComposer, prevWordForBigram));
                 }
             }
-
         } else if (wordComposer.size() > 1) {
             final WordComposer wordComposerForLookup;
-            if (mTrailingSingleQuotesCount > 0) {
+            if (trailingSingleQuotesCount > 0) {
                 wordComposerForLookup = new WordComposer(wordComposer);
-                for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+                for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) {
                     wordComposerForLookup.deleteLast();
                 }
             } else {
                 wordComposerForLookup = wordComposer;
             }
             // At second character typed, search the unigrams (scores being affected by bigrams)
-            for (final String key : mUnigramDictionaries.keySet()) {
+            for (final String key : mDictionaries.keySet()) {
                 // Skip UserUnigramDictionary and WhitelistDictionary to lookup
-                if (key.equals(DICT_KEY_USER_HISTORY_UNIGRAM) || key.equals(DICT_KEY_WHITELIST))
+                if (key.equals(Dictionary.TYPE_USER_HISTORY)
+                        || key.equals(Dictionary.TYPE_WHITELIST))
                     continue;
-                final Dictionary dictionary = mUnigramDictionaries.get(key);
-                dictionary.getWords(wordComposerForLookup, prevWordForBigram, this, proximityInfo);
+                final Dictionary dictionary = mDictionaries.get(key);
+                suggestionsSet.addAll(dictionary.getWords(
+                        wordComposerForLookup, prevWordForBigram, proximityInfo));
             }
         }
 
-        final CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase,
-                mIsFirstCharCapitalized, mWhiteListDictionary.getWhitelistedWord(consideredWord));
+        // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
+        // but still autocorrected from - in the case the whitelist only capitalizes the word.
+        // The whitelist should be case-insensitive, so it's not possible to be consistent with
+        // a boolean flag. Right now this is handled with a slight hack in
+        // WhitelistDictionary#shouldForciblyAutoCorrectFrom.
+        final boolean allowsToBeAutoCorrected = AutoCorrection.isWhitelistedOrNotAWord(
+                mDictionaries, consideredWord, wordComposer.isFirstCharCapitalized());
+
+        final CharSequence whitelistedWord =
+                mWhiteListDictionary.getWhitelistedWord(consideredWord);
 
         final boolean hasAutoCorrection;
-        if (isCorrectionEnabled) {
-            final CharSequence autoCorrection =
-                    AutoCorrection.computeAutoCorrectionWord(mUnigramDictionaries, wordComposer,
-                            mSuggestions, consideredWord, mAutoCorrectionThreshold,
-                            whitelistedWord);
-            hasAutoCorrection = (null != autoCorrection);
+        if (!isCorrectionEnabled || !allowsToBeAutoCorrected || wordComposer.isMostlyCaps()
+                || wordComposer.isResumed() || !hasMainDictionary()) {
+            // If we don't have a main dictionary, we never want to auto-correct. The reason for
+            // this is, the user may have a contact whose name happens to match a valid word in
+            // their language, and it will unexpectedly auto-correct. For example, if the user
+            // types in English with no dictionary and has a "Will" in their contact list, "will"
+            // would always auto-correct to "Will" which is unwanted. Hence, no main dict => no
+            // auto-correct.
+            hasAutoCorrection = false;
+        } else if (null != whitelistedWord) {
+            hasAutoCorrection = true;
+        } else if (suggestionsSet.isEmpty()) {
+            hasAutoCorrection = false;
+        } else if (AutoCorrection.suggestionExceedsAutoCorrectionThreshold(suggestionsSet.first(),
+                consideredWord, mAutoCorrectionThreshold)) {
+            hasAutoCorrection = true;
         } else {
             hasAutoCorrection = false;
         }
 
         if (whitelistedWord != null) {
-            if (mTrailingSingleQuotesCount > 0) {
-                final StringBuilder sb = new StringBuilder(whitelistedWord);
-                for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
-                    sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
-                }
-                mSuggestions.add(0, new SuggestedWordInfo(sb.toString(),
-                        SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST));
-            } else {
-                mSuggestions.add(0, new SuggestedWordInfo(whitelistedWord,
-                        SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST));
+            suggestionsSet.add(new SuggestedWordInfo(whitelistedWord,
+                    SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST,
+                    Dictionary.TYPE_WHITELIST));
+        }
+
+        final ArrayList<SuggestedWordInfo> suggestionsContainer =
+                new ArrayList<SuggestedWordInfo>(suggestionsSet);
+        final int suggestionsCount = suggestionsContainer.size();
+        if (isFirstCharCapitalized || isAllUpperCase || 0 != trailingSingleQuotesCount) {
+            for (int i = 0; i < suggestionsCount; ++i) {
+                final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+                final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
+                        wordInfo, mLocale, isAllUpperCase, isFirstCharCapitalized,
+                        trailingSingleQuotesCount);
+                suggestionsContainer.set(i, transformedWordInfo);
             }
         }
 
-        mSuggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
-                SuggestedWordInfo.KIND_TYPED));
-        SuggestedWordInfo.removeDups(mSuggestions);
+        for (int i = 0; i < suggestionsCount; ++i) {
+            final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+            LatinImeLogger.onAddSuggestedWord(wordInfo.mWord.toString(), wordInfo.mSourceDict);
+        }
+
+        if (!TextUtils.isEmpty(typedWord)) {
+            suggestionsContainer.add(0, new SuggestedWordInfo(typedWord,
+                    SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED,
+                    Dictionary.TYPE_USER_TYPED));
+        }
+        SuggestedWordInfo.removeDups(suggestionsContainer);
 
         final ArrayList<SuggestedWordInfo> suggestionsList;
-        if (DBG) {
-            suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, mSuggestions);
+        if (DBG && !suggestionsContainer.isEmpty()) {
+            suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, suggestionsContainer);
         } else {
-            suggestionsList = mSuggestions;
+            suggestionsList = suggestionsContainer;
         }
 
-        // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
-        // but still autocorrected from - in the case the whitelist only capitalizes the word.
-        // The whitelist should be case-insensitive, so it's not possible to be consistent with
-        // a boolean flag. Right now this is handled with a slight hack in
-        // WhitelistDictionary#shouldForciblyAutoCorrectFrom.
-        final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected(
-                getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized())
-        // If we don't have a main dictionary, we never want to auto-correct. The reason for this
-        // is, the user may have a contact whose name happens to match a valid word in their
-        // language, and it will unexpectedly auto-correct. For example, if the user types in
-        // English with no dictionary and has a "Will" in their contact list, "will" would
-        // always auto-correct to "Will" which is unwanted. Hence, no main dict => no auto-correct.
-                && hasMainDictionary();
-
-        boolean autoCorrectionAvailable = hasAutoCorrection;
-        if (isCorrectionEnabled) {
-            autoCorrectionAvailable |= !allowsToBeAutoCorrected;
-        }
-        // Don't auto-correct words with multiple capital letter
-        autoCorrectionAvailable &= !wordComposer.isMostlyCaps();
-        autoCorrectionAvailable &= !wordComposer.isResumed();
-        if (allowsToBeAutoCorrected && suggestionsList.size() > 1 && mAutoCorrectionThreshold > 0
-                && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord,
-                        suggestionsList.get(1).mWord)) {
-            autoCorrectionAvailable = false;
-        }
         return new SuggestedWords(suggestionsList,
-                !allowsToBeAutoCorrected /* typedWordValid */,
-                autoCorrectionAvailable /* hasAutoCorrectionCandidate */,
-                allowsToBeAutoCorrected /* allowsToBeAutoCorrected */,
+                // TODO: this first argument is lying. If this is a whitelisted word which is an
+                // actual word, it says typedWordValid = false, which looks wrong. We should either
+                // rename the attribute or change the value.
+                !isPrediction && !allowsToBeAutoCorrected /* typedWordValid */,
+                !isPrediction && hasAutoCorrection, /* willAutoCorrect */
                 false /* isPunctuationSuggestions */,
                 false /* isObsoleteSuggestions */,
-                false /* isPrediction */);
-    }
-
-    /**
-     * Adds all bigram predictions for prevWord. Also checks the lower case version of prevWord if
-     * it contains any upper case characters.
-     */
-    private void getAllBigrams(final CharSequence prevWord, final WordComposer wordComposer) {
-        if (StringUtils.hasUpperCase(prevWord)) {
-            // TODO: Must pay attention to locale when changing case.
-            final CharSequence lowerPrevWord = prevWord.toString().toLowerCase();
-            for (final Dictionary dictionary : mBigramDictionaries.values()) {
-                dictionary.getBigrams(wordComposer, lowerPrevWord, this);
-            }
-        }
-        for (final Dictionary dictionary : mBigramDictionaries.values()) {
-            dictionary.getBigrams(wordComposer, prevWord, this);
-        }
+                isPrediction);
     }
 
     private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
@@ -415,120 +311,44 @@ public class Suggest implements Dictionary.WordCallback {
         return suggestionsList;
     }
 
-    // TODO: Use codepoint instead of char
-    @Override
-    public boolean addWord(final char[] word, final int offset, final int length, int score,
-            final int dicTypeId, final int dataType) {
-        int dataTypeForLog = dataType;
-        final ArrayList<SuggestedWordInfo> suggestions;
-        final int prefMaxSuggestions;
-        if (dataType == Dictionary.BIGRAM) {
-            suggestions = mBigramSuggestions;
-            prefMaxSuggestions = PREF_MAX_BIGRAMS;
-        } else {
-            suggestions = mSuggestions;
-            prefMaxSuggestions = MAX_SUGGESTIONS;
+    private static class SuggestedWordInfoComparator implements Comparator<SuggestedWordInfo> {
+        // This comparator ranks the word info with the higher frequency first. That's because
+        // that's the order we want our elements in.
+        @Override
+        public int compare(final SuggestedWordInfo o1, final SuggestedWordInfo o2) {
+            if (o1.mScore > o2.mScore) return -1;
+            if (o1.mScore < o2.mScore) return 1;
+            if (o1.mCodePointCount < o2.mCodePointCount) return -1;
+            if (o1.mCodePointCount > o2.mCodePointCount) return 1;
+            return o1.mWord.toString().compareTo(o2.mWord.toString());
         }
-
-        int pos = 0;
-
-        // Check if it's the same word, only caps are different
-        if (StringUtils.equalsIgnoreCase(mConsideredWord, word, offset, length)) {
-            // TODO: remove this surrounding if clause and move this logic to
-            // getSuggestedWordBuilder.
-            if (suggestions.size() > 0) {
-                final SuggestedWordInfo currentHighestWord = suggestions.get(0);
-                // If the current highest word is also equal to typed word, we need to compare
-                // frequency to determine the insertion position. This does not ensure strictly
-                // correct ordering, but ensures the top score is on top which is enough for
-                // removing duplicates correctly.
-                if (StringUtils.equalsIgnoreCase(currentHighestWord.mWord, word, offset, length)
-                        && score <= currentHighestWord.mScore) {
-                    pos = 1;
-                }
-            }
-        } else {
-            // Check the last one's score and bail
-            if (suggestions.size() >= prefMaxSuggestions
-                    && suggestions.get(prefMaxSuggestions - 1).mScore >= score) return true;
-            while (pos < suggestions.size()) {
-                final int curScore = suggestions.get(pos).mScore;
-                if (curScore < score
-                        || (curScore == score && length < suggestions.get(pos).codePointCount())) {
-                    break;
-                }
-                pos++;
-            }
-        }
-        if (pos >= prefMaxSuggestions) {
-            return true;
-        }
-
-        final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
-        // TODO: Must pay attention to locale when changing case.
-        if (mIsAllUpperCase) {
-            sb.append(new String(word, offset, length).toUpperCase());
-        } else if (mIsFirstCharCapitalized) {
-            sb.append(Character.toUpperCase(word[offset]));
-            if (length > 1) {
-                sb.append(word, offset + 1, length - 1);
-            }
+    }
+    private static final SuggestedWordInfoComparator sSuggestedWordInfoComparator =
+            new SuggestedWordInfoComparator();
+
+    private static SuggestedWordInfo getTransformedSuggestedWordInfo(
+            final SuggestedWordInfo wordInfo, final Locale locale, final boolean isAllUpperCase,
+            final boolean isFirstCharCapitalized, final int trailingSingleQuotesCount) {
+        final StringBuilder sb = new StringBuilder(wordInfo.mWord.length());
+        if (isAllUpperCase) {
+            sb.append(wordInfo.mWord.toString().toUpperCase(locale));
+        } else if (isFirstCharCapitalized) {
+            sb.append(StringUtils.toTitleCase(wordInfo.mWord.toString(), locale));
         } else {
-            sb.append(word, offset, length);
+            sb.append(wordInfo.mWord);
         }
-        for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+        for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) {
             sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
         }
-        // TODO: figure out what type of suggestion this is
-        suggestions.add(pos, new SuggestedWordInfo(sb, score, SuggestedWordInfo.KIND_CORRECTION));
-        if (suggestions.size() > prefMaxSuggestions) {
-            suggestions.remove(prefMaxSuggestions);
-        } else {
-            LatinImeLogger.onAddSuggestedWord(sb.toString(), dicTypeId, dataTypeForLog);
-        }
-        return true;
+        return new SuggestedWordInfo(sb, wordInfo.mScore, wordInfo.mKind, wordInfo.mSourceDict);
     }
 
     public void close() {
         final HashSet<Dictionary> dictionaries = new HashSet<Dictionary>();
-        dictionaries.addAll(mUnigramDictionaries.values());
-        dictionaries.addAll(mBigramDictionaries.values());
+        dictionaries.addAll(mDictionaries.values());
         for (final Dictionary dictionary : dictionaries) {
             dictionary.close();
         }
         mMainDictionary = null;
     }
-
-    // TODO: Resolve the inconsistencies between the native auto correction algorithms and
-    // this safety net
-    public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord,
-            final CharSequence suggestion) {
-        // Safety net for auto correction.
-        // Actually if we hit this safety net, it's a bug.
-        // If user selected aggressive auto correction mode, there is no need to use the safety
-        // net.
-        // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
-        // we should not use net because relatively edit distance can be big.
-        final int typedWordLength = typedWord.length();
-        if (typedWordLength < Suggest.MINIMUM_SAFETY_NET_CHAR_LENGTH) {
-            return false;
-        }
-        final int maxEditDistanceOfNativeDictionary =
-                (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1;
-        final int distance = BinaryDictionary.editDistance(typedWord, suggestion.toString());
-        if (DBG) {
-            Log.d(TAG, "Autocorrected edit distance = " + distance
-                    + ", " + maxEditDistanceOfNativeDictionary);
-        }
-        if (distance > maxEditDistanceOfNativeDictionary) {
-            if (DBG) {
-                Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestion);
-                Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. "
-                        + "Turning off auto-correction.");
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 45ac9ff5362a84ee09228dd2f642f557630ff594..f079c211235ee02736214c93720442ec56113377 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -25,27 +25,27 @@ import java.util.HashSet;
 
 public class SuggestedWords {
     public static final SuggestedWords EMPTY = new SuggestedWords(
-            new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false, false);
+            new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false);
 
     public final boolean mTypedWordValid;
-    public final boolean mHasAutoCorrectionCandidate;
+    // Note: this INCLUDES cases where the word will auto-correct to itself. A good definition
+    // of what this flag means would be "the top suggestion is strong enough to auto-correct",
+    // whether this exactly matches the user entry or not.
+    public final boolean mWillAutoCorrect;
     public final boolean mIsPunctuationSuggestions;
-    public final boolean mAllowsToBeAutoCorrected;
     public final boolean mIsObsoleteSuggestions;
     public final boolean mIsPrediction;
     private final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList;
 
     public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
             final boolean typedWordValid,
-            final boolean hasAutoCorrectionCandidate,
-            final boolean allowsToBeAutoCorrected,
+            final boolean willAutoCorrect,
             final boolean isPunctuationSuggestions,
             final boolean isObsoleteSuggestions,
             final boolean isPrediction) {
         mSuggestedWordInfoList = suggestedWordInfoList;
         mTypedWordValid = typedWordValid;
-        mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate;
-        mAllowsToBeAutoCorrected = allowsToBeAutoCorrected;
+        mWillAutoCorrect = willAutoCorrect;
         mIsPunctuationSuggestions = isPunctuationSuggestions;
         mIsObsoleteSuggestions = isObsoleteSuggestions;
         mIsPrediction = isPrediction;
@@ -55,7 +55,7 @@ public class SuggestedWords {
         return mSuggestedWordInfoList.size();
     }
 
-    public CharSequence getWord(int pos) {
+    public String getWord(int pos) {
         return mSuggestedWordInfoList.get(pos).mWord;
     }
 
@@ -67,12 +67,8 @@ public class SuggestedWords {
         return mSuggestedWordInfoList.get(pos);
     }
 
-    public boolean hasAutoCorrectionWord() {
-        return mHasAutoCorrectionCandidate && size() > 1 && !mTypedWordValid;
-    }
-
     public boolean willAutoCorrect() {
-        return !mTypedWordValid && mHasAutoCorrectionCandidate;
+        return mWillAutoCorrect;
     }
 
     @Override
@@ -80,8 +76,7 @@ public class SuggestedWords {
         // Pretty-print method to help debug
         return "SuggestedWords:"
                 + " mTypedWordValid=" + mTypedWordValid
-                + " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate
-                + " mAllowsToBeAutoCorrected=" + mAllowsToBeAutoCorrected
+                + " mWillAutoCorrect=" + mWillAutoCorrect
                 + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions
                 + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray());
     }
@@ -92,7 +87,7 @@ public class SuggestedWords {
         for (CompletionInfo info : infos) {
             if (null != info && info.getText() != null) {
                 result.add(new SuggestedWordInfo(info.getText(), SuggestedWordInfo.MAX_SCORE,
-                        SuggestedWordInfo.KIND_APP_DEFINED));
+                        SuggestedWordInfo.KIND_APP_DEFINED, Dictionary.TYPE_APPLICATION_DEFINED));
             }
         }
         return result;
@@ -105,7 +100,7 @@ public class SuggestedWords {
         final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<SuggestedWordInfo>();
         final HashSet<String> alreadySeen = new HashSet<String>();
         suggestionsList.add(new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
-                SuggestedWordInfo.KIND_TYPED));
+                SuggestedWordInfo.KIND_TYPED, Dictionary.TYPE_USER_TYPED));
         alreadySeen.add(typedWord.toString());
         final int previousSize = previousSuggestions.size();
         for (int pos = 1; pos < previousSize; pos++) {
@@ -130,19 +125,20 @@ public class SuggestedWords {
         public static final int KIND_HARDCODED = 5; // Hardcoded suggestion, e.g. punctuation
         public static final int KIND_APP_DEFINED = 6; // Suggested by the application
         public static final int KIND_SHORTCUT = 7; // A shortcut
-        private final String mWordStr;
-        public final CharSequence mWord;
+        public final String mWord;
         public final int mScore;
         public final int mKind; // one of the KIND_* constants above
         public final int mCodePointCount;
+        public final String mSourceDict;
         private String mDebugString = "";
 
-        public SuggestedWordInfo(final CharSequence word, final int score, final int kind) {
-            mWordStr = word.toString();
-            mWord = word;
+        public SuggestedWordInfo(final CharSequence word, final int score, final int kind,
+                final String sourceDict) {
+            mWord = word.toString();
             mScore = score;
             mKind = kind;
-            mCodePointCount = mWordStr.codePointCount(0, mWordStr.length());
+            mSourceDict = sourceDict;
+            mCodePointCount = StringUtils.codePointCount(mWord);
         }
 
 
@@ -160,15 +156,15 @@ public class SuggestedWords {
         }
 
         public int codePointAt(int i) {
-            return mWordStr.codePointAt(i);
+            return mWord.codePointAt(i);
         }
 
         @Override
         public String toString() {
             if (TextUtils.isEmpty(mDebugString)) {
-                return mWordStr;
+                return mWord;
             } else {
-                return mWordStr + " (" + mDebugString.toString() + ")";
+                return mWord + " (" + mDebugString.toString() + ")";
             }
         }
 
@@ -182,7 +178,7 @@ public class SuggestedWords {
                 final SuggestedWordInfo cur = candidates.get(i);
                 for (int j = 0; j < i; ++j) {
                     final SuggestedWordInfo previous = candidates.get(j);
-                    if (TextUtils.equals(cur.mWord, previous.mWord)) {
+                    if (cur.mWord.equals(previous.mWord)) {
                         candidates.remove(cur.mScore < previous.mScore ? i : j);
                         --i;
                         break;
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 673b54500849aea756dae203ade15c8fbef50bd8..9b20bd690358a9bf17b9786d9906320d83c52a6f 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -19,22 +19,23 @@ package com.android.inputmethod.latin;
 import android.content.Context;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 
+import java.util.ArrayList;
 import java.util.Locale;
 
 public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary {
     private boolean mClosed;
 
     public SynchronouslyLoadedContactsBinaryDictionary(final Context context, final Locale locale) {
-        super(context, Suggest.DIC_CONTACTS, locale);
+        super(context, locale);
     }
 
     @Override
-    public synchronized void getWords(final WordComposer codes,
-            final CharSequence prevWordForBigrams, final WordCallback callback,
-            final ProximityInfo proximityInfo) {
+    public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
         syncReloadDictionaryIfRequired();
-        getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+        return getWordsInner(codes, prevWordForBigrams, proximityInfo);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
index 1606a34e077dbe95cf4ec39770a2fde724bb42ec..5b2a6edec309d9ddafc3da309b17f49bf89b3755 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -19,6 +19,9 @@ package com.android.inputmethod.latin;
 import android.content.Context;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
 
 public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary {
 
@@ -32,11 +35,10 @@ public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionar
     }
 
     @Override
-    public synchronized void getWords(final WordComposer codes,
-            final CharSequence prevWordForBigrams, final WordCallback callback,
-            final ProximityInfo proximityInfo) {
+    public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
         syncReloadDictionaryIfRequired();
-        getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+        return getWordsInner(codes, prevWordForBigrams, proximityInfo);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 5bcdb57b5eb3838a3eb2641fc255c4ba0aa807ca..60e6fa12797396b41252b5c212a567f1316fb92b 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -34,7 +34,10 @@ import java.util.Arrays;
  */
 public class UserBinaryDictionary extends ExpandableBinaryDictionary {
 
-    // TODO: use Words.SHORTCUT when it's public in the SDK
+    // The user dictionary provider uses an empty string to mean "all languages".
+    private static final String USER_DICTIONARY_ALL_LANGUAGES = "";
+
+    // TODO: use Words.SHORTCUT when we target JellyBean or above
     final static String SHORTCUT = "shortcut";
     private static final String[] PROJECTION_QUERY;
     static {
@@ -69,9 +72,14 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
 
     public UserBinaryDictionary(final Context context, final String locale,
             final boolean alsoUseMoreRestrictiveLocales) {
-        super(context, getFilenameWithLocale(NAME, locale), Suggest.DIC_USER);
+        super(context, getFilenameWithLocale(NAME, locale), Dictionary.TYPE_USER);
         if (null == locale) throw new NullPointerException(); // Catch the error earlier
-        mLocale = locale;
+        if (SubtypeLocale.NO_LANGUAGE.equals(locale)) {
+            // If we don't have a locale, insert into the "all locales" user dictionary.
+            mLocale = USER_DICTIONARY_ALL_LANGUAGES;
+        } else {
+            mLocale = locale;
+        }
         mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
         // Perform a managed query. The Activity will handle closing and re-querying the cursor
         // when needed.
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
index 5095f65822551783335a3d310a3ae951f868ab15..73fa83f9ad03520844b0b5ceb14ca668e63dc558 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -115,8 +115,7 @@ public class UserHistoryDictionary extends ExpandableDictionary {
     }
 
     public synchronized static UserHistoryDictionary getInstance(
-            final Context context, final String locale,
-            final int dictTypeId, final SharedPreferences sp) {
+            final Context context, final String locale, final SharedPreferences sp) {
         if (sLangDictCache.containsKey(locale)) {
             final SoftReference<UserHistoryDictionary> ref = sLangDictCache.get(locale);
             final UserHistoryDictionary dict = ref == null ? null : ref.get();
@@ -128,14 +127,14 @@ public class UserHistoryDictionary extends ExpandableDictionary {
             }
         }
         final UserHistoryDictionary dict =
-                new UserHistoryDictionary(context, locale, dictTypeId, sp);
+                new UserHistoryDictionary(context, locale, sp);
         sLangDictCache.put(locale, new SoftReference<UserHistoryDictionary>(dict));
         return dict;
     }
 
-    private UserHistoryDictionary(final Context context, final String locale, final int dicTypeId,
-            SharedPreferences sp) {
-        super(context, dicTypeId);
+    private UserHistoryDictionary(final Context context, final String locale,
+            final SharedPreferences sp) {
+        super(context, Dictionary.TYPE_USER_HISTORY);
         mLocale = locale;
         mPrefs = sp;
         if (sOpenHelper == null) {
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index a44b1f9ad7b5d43b39e6a0f5f14323aace5ae569..8f71de0e7ae009996459eff819e880586492ccf4 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -531,14 +531,4 @@ public class Utils {
         }
         return builder.toString();
     }
-
-    public static void addAllSuggestions(final int dicTypeId, final int dataType,
-            final ArrayList<SuggestedWords.SuggestedWordInfo> suggestions,
-            final Dictionary.WordCallback callback) {
-        for (SuggestedWordInfo suggestion : suggestions) {
-            final String suggestionStr = suggestion.mWord.toString();
-            callback.addWord(suggestionStr.toCharArray(), 0, suggestionStr.length(),
-                    suggestion.mScore, dicTypeId, dataType);
-        }
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
index a0de2f9707746ca0b0af798c3f8f6cfd6b0b5e69..3af22140ec95adb22a857d82b883b57ae96a8218 100644
--- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
+++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
@@ -37,7 +37,7 @@ public class WhitelistDictionary extends ExpandableDictionary {
 
     // TODO: Conform to the async load contact of ExpandableDictionary
     public WhitelistDictionary(final Context context, final Locale locale) {
-        super(context, Suggest.DIC_WHITELIST);
+        super(context, Dictionary.TYPE_WHITELIST);
         // TODO: Move whitelist dictionary into main dictionary.
         final RunInLocale<Void> job = new RunInLocale<Void>() {
             @Override
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 43b92337af1b24d6651f07926962dcf0987be663..bf5e05e9bac321b93f99c628966020c556793942 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -33,8 +33,7 @@ public class WordComposer {
     private static final int N = BinaryDictionary.MAX_WORD_LENGTH;
 
     private int[] mPrimaryKeyCodes;
-    private int[] mXCoordinates;
-    private int[] mYCoordinates;
+    private final InputPointers mInputPointers = new InputPointers();
     private StringBuilder mTypedWord;
     private CharSequence mAutoCorrection;
     private boolean mIsResumed;
@@ -53,8 +52,6 @@ public class WordComposer {
     public WordComposer() {
         mPrimaryKeyCodes = new int[N];
         mTypedWord = new StringBuilder(N);
-        mXCoordinates = new int[N];
-        mYCoordinates = new int[N];
         mAutoCorrection = null;
         mTrailingSingleQuotesCount = 0;
         mIsResumed = false;
@@ -68,8 +65,7 @@ public class WordComposer {
     public void init(WordComposer source) {
         mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length);
         mTypedWord = new StringBuilder(source.mTypedWord);
-        mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length);
-        mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length);
+        mInputPointers.copy(source.mInputPointers);
         mCapsCount = source.mCapsCount;
         mIsFirstCharCapitalized = source.mIsFirstCharCapitalized;
         mAutoCapitalized = source.mAutoCapitalized;
@@ -91,7 +87,7 @@ public class WordComposer {
         refreshSize();
     }
 
-    public final void refreshSize() {
+    private final void refreshSize() {
         mCodePointSize = mTypedWord.codePointCount(0, mTypedWord.length());
     }
 
@@ -115,12 +111,8 @@ public class WordComposer {
         return mPrimaryKeyCodes[index];
     }
 
-    public int[] getXCoordinates() {
-        return mXCoordinates;
-    }
-
-    public int[] getYCoordinates() {
-        return mYCoordinates;
+    public InputPointers getInputPointers() {
+        return mInputPointers;
     }
 
     private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) {
@@ -138,8 +130,8 @@ public class WordComposer {
         if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
             mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE
                     ? Character.toLowerCase(primaryCode) : primaryCode;
-            mXCoordinates[newIndex] = keyX;
-            mYCoordinates[newIndex] = keyY;
+            // TODO: Set correct pointer id and time
+            mInputPointers.addPointer(newIndex, keyX, keyY, 0, 0);
         }
         mIsFirstCharCapitalized = isFirstCharCapitalized(
                 newIndex, primaryCode, mIsFirstCharCapitalized);
@@ -298,14 +290,11 @@ public class WordComposer {
         // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
         // the last composed word to ensure this does not happen.
         final int[] primaryKeyCodes = mPrimaryKeyCodes;
-        final int[] xCoordinates = mXCoordinates;
-        final int[] yCoordinates = mYCoordinates;
         mPrimaryKeyCodes = new int[N];
-        mXCoordinates = new int[N];
-        mYCoordinates = new int[N];
         final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes,
-                xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode,
+                mInputPointers, mTypedWord.toString(), committedWord, separatorCode,
                 prevWord);
+        mInputPointers.reset();
         if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
                 && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
             lastComposedWord.deactivate();
@@ -319,8 +308,7 @@ public class WordComposer {
 
     public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) {
         mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes;
-        mXCoordinates = lastComposedWord.mXCoordinates;
-        mYCoordinates = lastComposedWord.mYCoordinates;
+        mInputPointers.set(lastComposedWord.mInputPointers);
         mTypedWord.setLength(0);
         mTypedWord.append(lastComposedWord.mTypedWord);
         refreshSize();
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 69b48cecc117e2f90627dcef0f97b0bc77d7c487..5332c066a014c10283a5d5849c79c49ce670bbcc 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -32,12 +32,12 @@ import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.BinaryDictionary;
 import com.android.inputmethod.latin.ContactsBinaryDictionary;
 import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.Dictionary.WordCallback;
 import com.android.inputmethod.latin.DictionaryCollection;
 import com.android.inputmethod.latin.DictionaryFactory;
 import com.android.inputmethod.latin.LocaleUtils;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.SynchronouslyLoadedContactsBinaryDictionary;
 import com.android.inputmethod.latin.SynchronouslyLoadedUserBinaryDictionary;
 import com.android.inputmethod.latin.UserBinaryDictionary;
@@ -203,7 +203,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
                 EMPTY_STRING_ARRAY);
     }
 
-    private static class SuggestionsGatherer implements WordCallback {
+    // TODO: remove this class and replace it by storage local to the session.
+    private static class SuggestionsGatherer {
         public static class Result {
             public final String[] mSuggestions;
             public final boolean mHasRecommendedSuggestions;
@@ -237,9 +238,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
             mScores = new int[mMaxLength];
         }
 
-        @Override
-        synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score,
-                int dicTypeId, int dataType) {
+        synchronized public boolean addWord(char[] word, int[] spaceIndices, int wordOffset,
+                int wordLength, int score) {
             final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score);
             // binarySearch returns the index if the element exists, and -<insertion index> - 1
             // if it doesn't. See documentation for binarySearch.
@@ -780,8 +780,13 @@ public class AndroidSpellCheckerService extends SpellCheckerService
                 try {
                     dictInfo = mDictionaryPool.takeOrGetNull();
                     if (null == dictInfo) return getNotInDictEmptySuggestions();
-                    dictInfo.mDictionary.getWords(composer, prevWord, suggestionsGatherer,
-                            dictInfo.mProximityInfo);
+                    final ArrayList<SuggestedWordInfo> suggestions = dictInfo.mDictionary.getWords(
+                            composer, prevWord, dictInfo.mProximityInfo);
+                    for (final SuggestedWordInfo suggestion : suggestions) {
+                        final String suggestionStr = suggestion.mWord.toString();
+                        suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0,
+                                suggestionStr.length(), suggestion.mScore);
+                    }
                     isInDict = dictInfo.mDictionary.isValidWord(text);
                     if (!isInDict && CAPITALIZE_NONE != capitalizeType) {
                         // We want to test the word again if it's all caps or first caps only.
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
index e86390b11dca7ea889e8d397b2de5e31d0ec008b..642a551ceeb7713533ae71812a601018e0d98171 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
@@ -57,11 +57,11 @@ import com.android.inputmethod.keyboard.KeyboardView;
 import com.android.inputmethod.keyboard.MoreKeysPanel;
 import com.android.inputmethod.keyboard.PointerTracker;
 import com.android.inputmethod.keyboard.ViewLayoutUtils;
+import com.android.inputmethod.latin.AutoCorrection;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.ResearchLogger;
 import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
-import com.android.inputmethod.latin.Suggest;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.define.ProductionFlag;
@@ -336,8 +336,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
             if (LatinImeLogger.sDBG && suggestedWords.size() > 1) {
                 // If we auto-correct, then the autocorrection is in slot 0 and the typed word
                 // is in slot 1.
-                if (index == mCenterSuggestionIndex && suggestedWords.mHasAutoCorrectionCandidate
-                        && Suggest.shouldBlockAutoCorrectionBySafetyNet(
+                if (index == mCenterSuggestionIndex
+                        && AutoCorrection.shouldBlockAutoCorrectionBySafetyNet(
                                 suggestedWords.getWord(1).toString(), suggestedWords.getWord(0))) {
                     return 0xFFFF0000;
                 }
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index 14b1e6454e9849299608a3db8e33bc28f2130629..d40063ed5a1cce107e1118bffaf256427b9ba6d4 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -17,15 +17,16 @@ LOCAL_PATH := $(call my-dir)
 ############ some local flags
 # If you change any of those flags, you need to rebuild both libjni_latinime_static
 # and the shared library.
-#FLAG_DBG := true
+FLAG_DBG ?= false
 FLAG_DO_PROFILE ?= false
 
 ######################################
 include $(CLEAR_VARS)
 
 LATIN_IME_SRC_DIR := src
+LATIN_IME_SRC_FULLPATH_DIR := $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
 
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
+LOCAL_C_INCLUDES += $(LATIN_IME_SRC_FULLPATH_DIR) $(LATIN_IME_SRC_FULLPATH_DIR)/gesture
 
 LOCAL_CFLAGS += -Werror -Wall
 
@@ -47,11 +48,12 @@ LATIN_IME_CORE_SRC_FILES := \
     dictionary.cpp \
     proximity_info.cpp \
     proximity_info_state.cpp \
-    unigram_dictionary.cpp
+    unigram_dictionary.cpp \
+    gesture/gesture_decoder_wrapper.cpp
 
 LOCAL_SRC_FILES := \
     $(LATIN_IME_JNI_SRC_FILES) \
-    $(addprefix $(LATIN_IME_SRC_DIR)/,$(LATIN_IME_CORE_SRC_FILES))
+    $(addprefix $(LATIN_IME_SRC_DIR)/, $(LATIN_IME_CORE_SRC_FILES))
 
 ifeq ($(FLAG_DO_PROFILE), true)
     $(warning Making profiling version of native library)
@@ -73,12 +75,11 @@ LOCAL_C_INCLUDES += external/stlport/stlport bionic
 endif
 
 include $(BUILD_STATIC_LIBRARY)
-
 ######################################
 include $(CLEAR_VARS)
 
 # All code in LOCAL_WHOLE_STATIC_LIBRARIES will be built into this shared library.
-LOCAL_WHOLE_STATIC_LIBRARIES := libjni_latinime_static
+LOCAL_WHOLE_STATIC_LIBRARIES := libjni_latinime_common_static
 
 ifdef HISTORICAL_NDK_VERSIONS_ROOT # In the platform build system
 LOCAL_SHARED_LIBRARIES := libstlport
@@ -108,5 +109,6 @@ include $(BUILD_SHARED_LIBRARY)
 #################### Clean up the tmp vars
 LATIN_IME_CORE_SRC_FILES :=
 LATIN_IME_JNI_SRC_FILES :=
+LATIN_IME_GESTURE_IMPL_SRC_FILES :=
 LATIN_IME_SRC_DIR :=
-TARGETING_UNBUNDLED_FROYO :=
+LATIN_IME_SRC_FULLPATH_DIR :=
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index d10dc962e5d4020bd547778154b2567db7610b6a..bee0662eebbad70efeca35e791cd36a9ebf397aa 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -128,28 +128,37 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
 
 static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict,
         jlong proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray,
-        jintArray inputArray, jint arraySize, jintArray prevWordForBigrams,
-        jboolean useFullEditDistance, jcharArray outputArray, jintArray frequencyArray) {
-    Dictionary *dictionary = (Dictionary*)dict;
+        jintArray timesArray, jintArray pointerIdArray, jintArray inputArray, jint arraySize,
+        jint commitPoint, jboolean isGesture,
+        jintArray prevWordForBigrams, jboolean useFullEditDistance, jcharArray outputArray,
+        jintArray frequencyArray, jintArray spaceIndexArray) {
+    Dictionary *dictionary = (Dictionary*) dict;
     if (!dictionary) return 0;
     ProximityInfo *pInfo = (ProximityInfo*)proximityInfo;
     int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, 0);
     int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, 0);
+    int *times = env->GetIntArrayElements(timesArray, 0);
+    int *pointerIds = env->GetIntArrayElements(pointerIdArray, 0);
     int *frequencies = env->GetIntArrayElements(frequencyArray, 0);
     int *inputCodes = env->GetIntArrayElements(inputArray, 0);
     jchar *outputChars = env->GetCharArrayElements(outputArray, 0);
+    int *spaceIndices = env->GetIntArrayElements(spaceIndexArray, 0);
     jint *prevWordChars = prevWordForBigrams
             ? env->GetIntArrayElements(prevWordForBigrams, 0) : 0;
     jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0;
-    int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, inputCodes,
-            arraySize, prevWordChars, prevWordLength, useFullEditDistance,
-            (unsigned short*) outputChars, frequencies);
+    int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, times, pointerIds,
+            inputCodes, arraySize, prevWordChars, prevWordLength, commitPoint, isGesture,
+            useFullEditDistance, (unsigned short*) outputChars,
+            frequencies, spaceIndices);
     if (prevWordChars) {
         env->ReleaseIntArrayElements(prevWordForBigrams, prevWordChars, JNI_ABORT);
     }
+    env->ReleaseIntArrayElements(spaceIndexArray, spaceIndices, 0);
     env->ReleaseCharArrayElements(outputArray, outputChars, 0);
     env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
     env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
+    env->ReleaseIntArrayElements(pointerIdArray, pointerIds, 0);
+    env->ReleaseIntArrayElements(timesArray, times, 0);
     env->ReleaseIntArrayElements(yCoordinatesArray, yCoordinates, 0);
     env->ReleaseIntArrayElements(xCoordinatesArray, xCoordinates, 0);
     return count;
@@ -251,8 +260,8 @@ void releaseDictBuf(void* dictBuf, const size_t length, int fd) {
 static JNINativeMethod sMethods[] = {
     {"openNative", "(Ljava/lang/String;JJIIII)J", (void*)latinime_BinaryDictionary_open},
     {"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close},
-    {"getSuggestionsNative", "(JJ[I[I[II[IZ[C[I)I",
-            (void*)latinime_BinaryDictionary_getSuggestions},
+    {"getSuggestionsNative", "(JJ[I[I[I[I[IIIZ[IZ[C[I[I)I",
+            (void*) latinime_BinaryDictionary_getSuggestions},
     {"getFrequencyNative", "(J[II)I", (void*)latinime_BinaryDictionary_getFrequency},
     {"isValidBigramNative", "(J[I[I)Z", (void*)latinime_BinaryDictionary_isValidBigram},
     {"getBigramsNative", "(J[II[II[C[III)I", (void*)latinime_BinaryDictionary_getBigrams},
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 8bcadcbe9d65e486755b6e08cd973e230a0e1bf1..c7d3bf31360c60a5543e32a1a43e2fc62db87c76 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -255,6 +255,8 @@ static inline void prof_out(void) {
 
 #define FIRST_WORD_INDEX 0
 
+#define MAX_SPACES_INTERNAL 16
+
 // TODO: Reduce this constant if possible; check the maximum number of digraphs in the same
 // word in the dictionary for languages with digraphs, like German and French
 #define DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH 5
diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp
index 83bb267311f4326eb9de0d45b91192b88b586afd..628a1693300e90c6b45a7a56f70710265ddccb26 100644
--- a/native/jni/src/dictionary.cpp
+++ b/native/jni/src/dictionary.cpp
@@ -22,6 +22,7 @@
 #include "binary_format.h"
 #include "defines.h"
 #include "dictionary.h"
+#include "gesture_decoder_wrapper.h"
 
 namespace latinime {
 
@@ -43,11 +44,15 @@ Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust,
     mUnigramDictionary = new UnigramDictionary(mDict + headerSize, typedLetterMultiplier,
             fullWordMultiplier, maxWordLength, maxWords, options);
     mBigramDictionary = new BigramDictionary(mDict + headerSize, maxWordLength);
+    mGestureDecoder = new GestureDecoderWrapper(maxWordLength, maxWords);
+    mGestureDecoder->setDict(mUnigramDictionary, mBigramDictionary,
+            mDict + headerSize /* dict root */, 0 /* root pos */);
 }
 
 Dictionary::~Dictionary() {
     delete mUnigramDictionary;
     delete mBigramDictionary;
+    delete mGestureDecoder;
 }
 
 int Dictionary::getFrequency(const int32_t *word, int length) const {
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index fd69f79e3633a11c4d4cb13f3808a5cc2d7ee1bf..431f10337f66331714e4d9ff1d62ce801aac049e 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -22,6 +22,7 @@
 #include "bigram_dictionary.h"
 #include "char_utils.h"
 #include "defines.h"
+#include "incremental_decoder_interface.h"
 #include "proximity_info.h"
 #include "unigram_dictionary.h"
 #include "words_priority_queue_pool.h"
@@ -34,15 +35,27 @@ class Dictionary {
             int fullWordMultiplier, int maxWordLength, int maxWords);
 
     int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates,
-            int *codes, int codesSize, const int32_t* prevWordChars, const int prevWordLength,
-            bool useFullEditDistance, unsigned short *outWords, int *frequencies) const {
-        std::map<int, int> bigramMap;
-        uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE];
-        mBigramDictionary->fillBigramAddressToFrequencyMapAndFilter(prevWordChars,
-                prevWordLength, &bigramMap, bigramFilter);
-        return mUnigramDictionary->getSuggestions(proximityInfo,
-                xcoordinates, ycoordinates, codes, codesSize, &bigramMap,
-                bigramFilter, useFullEditDistance, outWords, frequencies);
+            int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars,
+            int prevWordLength, int commitPoint, bool isGesture,
+            bool useFullEditDistance, unsigned short *outWords,
+            int *frequencies, int *spaceIndices) {
+        int result = 0;
+        if (isGesture) {
+            mGestureDecoder->setPrevWord(prevWordChars, prevWordLength);
+            result = mGestureDecoder->getSuggestions(proximityInfo, xcoordinates, ycoordinates,
+                    times, pointerIds, codes, codesSize, commitPoint,
+                    outWords, frequencies, spaceIndices);
+            return result;
+        } else {
+            std::map<int, int> bigramMap;
+            uint8_t bigramFilter[BIGRAM_FILTER_BYTE_SIZE];
+            mBigramDictionary->fillBigramAddressToFrequencyMapAndFilter(prevWordChars,
+                    prevWordLength, &bigramMap, bigramFilter);
+            result = mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates,
+                    ycoordinates, codes, codesSize, &bigramMap, bigramFilter,
+                    useFullEditDistance, outWords, frequencies);
+            return result;
+        }
     }
 
     int getBigrams(const int32_t *word, int length, int *codes, int codesSize,
@@ -75,6 +88,7 @@ class Dictionary {
 
     const UnigramDictionary *mUnigramDictionary;
     const BigramDictionary *mBigramDictionary;
+    IncrementalDecoderInterface *mGestureDecoder;
 };
 
 // public static utility methods
diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.cpp b/native/jni/src/gesture/gesture_decoder_wrapper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..afbe0c5c3e58393e3088580aa67404c58c01f1cf
--- /dev/null
+++ b/native/jni/src/gesture/gesture_decoder_wrapper.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gesture_decoder_wrapper.h"
+
+namespace latinime {
+    IncrementalDecoderInterface *
+            (*GestureDecoderWrapper::sGestureDecoderFactoryMethod)(int, int) = 0;
+} // namespace latinime
diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.h b/native/jni/src/gesture/gesture_decoder_wrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..35982f03d8a16e585b5084df4ccf0de2abb70470
--- /dev/null
+++ b/native/jni/src/gesture/gesture_decoder_wrapper.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_GESTURE_DECODER_WRAPPER_H
+#define LATINIME_GESTURE_DECODER_WRAPPER_H
+
+#include <stdint.h>
+#include "defines.h"
+#include "incremental_decoder_interface.h"
+
+namespace latinime {
+
+class UnigramDictionary;
+class BigramDictionary;
+class ProximityInfo;
+
+class GestureDecoderWrapper : public IncrementalDecoderInterface {
+ public:
+    GestureDecoderWrapper(const int maxWordLength, const int maxWords) {
+        mIncrementalDecoderInterface = getGestureDecoderInstance(maxWordLength, maxWords);
+    }
+
+    virtual ~GestureDecoderWrapper() {
+        delete mIncrementalDecoderInterface;
+    }
+
+    int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times,
+            int *pointerIds, int *codes, int inputSize, int commitPoint,
+            unsigned short *outWords, int *frequencies, int *outputIndices) {
+        if (!mIncrementalDecoderInterface) {
+            return 0;
+        }
+        return mIncrementalDecoderInterface->getSuggestions(
+                pInfo, inputXs, inputYs, times, pointerIds, codes, inputSize, commitPoint,
+                outWords, frequencies, outputIndices);
+    }
+
+    void reset() {
+        if (!mIncrementalDecoderInterface) {
+            return;
+        }
+        mIncrementalDecoderInterface->reset();
+    }
+
+    void setDict(const UnigramDictionary *dict, const BigramDictionary *bigram,
+            const uint8_t *dictRoot, int rootPos) {
+        if (!mIncrementalDecoderInterface) {
+            return;
+        }
+        mIncrementalDecoderInterface->setDict(dict, bigram, dictRoot, rootPos);
+    }
+
+    void setPrevWord(const int32_t *prevWord, int prevWordLength) {
+        if (!mIncrementalDecoderInterface) {
+            return;
+        }
+        mIncrementalDecoderInterface->setPrevWord(prevWord, prevWordLength);
+    }
+
+    static void setGestureDecoderFactoryMethod(
+            IncrementalDecoderInterface *(*factoryMethod)(int, int)) {
+        sGestureDecoderFactoryMethod = factoryMethod;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(GestureDecoderWrapper);
+    static IncrementalDecoderInterface *getGestureDecoderInstance(int maxWordLength, int maxWords) {
+        if (sGestureDecoderFactoryMethod) {
+            return sGestureDecoderFactoryMethod(maxWordLength, maxWords);
+        }
+        return 0;
+    }
+
+    static IncrementalDecoderInterface *(*sGestureDecoderFactoryMethod)(int, int);
+    IncrementalDecoderInterface *mIncrementalDecoderInterface;
+};
+} // namespace latinime
+#endif // LATINIME_GESTURE_DECODER_WRAPPER_H
diff --git a/native/jni/src/gesture/incremental_decoder_interface.h b/native/jni/src/gesture/incremental_decoder_interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..957f1ebbe55f9c50070f674672488460854ad07f
--- /dev/null
+++ b/native/jni/src/gesture/incremental_decoder_interface.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_INCREMENTAL_DECODER_INTERFACE_H
+#define LATINIME_INCREMENTAL_DECODER_INTERFACE_H
+
+#include <stdint.h>
+#include "defines.h"
+
+namespace latinime {
+
+class UnigramDictionary;
+class BigramDictionary;
+class ProximityInfo;
+
+class IncrementalDecoderInterface {
+ public:
+    virtual int getSuggestions(ProximityInfo *pInfo, int *inputXs, int *inputYs, int *times,
+            int *pointerIds, int *codes, int inputSize, int commitPoint,
+            unsigned short *outWords, int *frequencies, int *outputIndices) = 0;
+    virtual void reset() = 0;
+    virtual void setDict(const UnigramDictionary *dict, const BigramDictionary *bigram,
+            const uint8_t *dictRoot, int rootPos) = 0;
+    virtual void setPrevWord(const int32_t *prevWord, int prevWordLength) = 0;
+    virtual ~IncrementalDecoderInterface() { };
+};
+} // namespace latinime
+#endif // LATINIME_INCREMENTAL_DECODER_INTERFACE_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index 2ba244a7c9470fc459fd3e13f1bfe6cbf9128fc3..a4a641160b6d6f7e0e75e06c955390e8bcfbedae 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <assert.h>
+#include <math.h>
 #include <stdio.h>
 #include <string>
 
@@ -210,4 +211,25 @@ int ProximityInfo::getKeyIndex(const int c) const {
     }
     return mCodeToKeyIndex[baseLowerC];
 }
+
+// TODO: [Staging] Optimize
+void ProximityInfo::getCenters(int *centerXs, int *centerYs, int *codeToKeyIndex,
+        int *keyToCodeIndex, int *keyCount, int *keyWidth) const {
+    *keyCount = KEY_COUNT;
+    *keyWidth = sqrt((float)MOST_COMMON_KEY_WIDTH_SQUARE);
+
+    for (int i = 0; i < KEY_COUNT; ++i) {
+        const int code = mKeyCharCodes[i];
+        const int lowerCode = toBaseLowerCase(code);
+        centerXs[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2;
+        centerYs[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2;
+        codeToKeyIndex[code] = i;
+        if (code != lowerCode && lowerCode >= 0 && lowerCode <= MAX_CHAR_CODE) {
+            codeToKeyIndex[lowerCode] = i;
+            keyToCodeIndex[i] = lowerCode;
+        } else {
+            keyToCodeIndex[i] = code;
+        }
+    }
+}
 } // namespace latinime
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index fec6555ea5bccd974ff66a71e955c799ecefffdc..d58935c6b0823ae36459de770862fa8149f947a6 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -98,6 +98,10 @@ class ProximityInfo {
         return GRID_HEIGHT;
     }
 
+    // Returns the keyboard key-center information.
+    void getCenters(int *centersX, int *centersY, int *codeToKeyIndex, int *keyToCodeIndex,
+            int *keyCount, int *keyWidth) const;
+
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfo);
     // The max number of the keys in one keyboard layout