diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 5bc9b6281c630d5994536daa08ba2b4a93e379a7..67ca59540c6478559822e77aabfda8cf853b2949 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -169,6 +169,8 @@ public final class Constants {
     // How many continuous deletes at which to start deleting at a higher speed.
     public static final int DELETE_ACCELERATE_AT = 20;
 
+    public static final String WORD_SEPARATOR = " ";
+
     public static boolean isValidCoordinate(final int coordinate) {
         // Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
         // and {@link SPELL_CHECKER_COORDINATE}.
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index ea9691a5abba76d260152013440f2944c4da0f90..3babb4195588864ec3af83fa720e54a3dbbe253a 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -56,7 +56,7 @@ public class DictionaryFacilitatorForSuggest {
     private boolean mIsUserDictEnabled = false;
     private volatile CountDownLatch mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
     // To synchronize assigning mDictionaries to ensure closing dictionaries.
-    private Object mLock = new Object();
+    private final Object mLock = new Object();
 
     private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTION =
             new String[] {
@@ -372,30 +372,42 @@ public class DictionaryFacilitatorForSuggest {
     public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
             final String previousWord, final int timeStampInSeconds) {
         final Dictionaries dictionaries = mDictionaries;
+        final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
+        for (int i = 0; i < words.length; i++) {
+            final String currentWord = words[i];
+            final String prevWord = (i == 0) ? previousWord : words[i - 1];
+            final boolean wasCurrentWordAutoCapitalized = (i == 0) ? wasAutoCapitalized : false;
+            addWordToUserHistory(dictionaries, prevWord, currentWord,
+                    wasCurrentWordAutoCapitalized, timeStampInSeconds);
+        }
+    }
+
+    private void addWordToUserHistory(final Dictionaries dictionaries, final String prevWord,
+            final String word, final boolean wasAutoCapitalized, final int timeStampInSeconds) {
         final ExpandableBinaryDictionary userHistoryDictionary =
                 dictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
         if (userHistoryDictionary == null) {
             return;
         }
-        final int maxFreq = getMaxFrequency(suggestion);
+        final int maxFreq = getMaxFrequency(word);
         if (maxFreq == 0) {
             return;
         }
-        final String suggestionLowerCase = suggestion.toLowerCase(dictionaries.mLocale);
+        final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
         final String secondWord;
         if (wasAutoCapitalized) {
-            if (isValidWord(suggestion, false /* ignoreCase */)
-                    && !isValidWord(suggestionLowerCase, false /* ignoreCase */)) {
+            if (isValidWord(word, false /* ignoreCase */)
+                    && !isValidWord(lowerCasedWord, false /* ignoreCase */)) {
                 // If the word was auto-capitalized and exists only as a capitalized word in the
                 // dictionary, then we must not downcase it before registering it. For example,
                 // the name of the contacts in start-of-sentence position would come here with the
                 // wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version
                 // of that contact's name which would end up popping in suggestions.
-                secondWord = suggestion;
+                secondWord = word;
             } else {
                 // If however the word is not in the dictionary, or exists as a lower-case word
                 // only, then we consider that was a lower-case word that had been auto-capitalized.
-                secondWord = suggestionLowerCase;
+                secondWord = lowerCasedWord;
             }
         } else {
             // HACK: We'd like to avoid adding the capitalized form of common words to the User
@@ -403,20 +415,20 @@ public class DictionaryFacilitatorForSuggest {
             // consolidation is done.
             // TODO: Remove this hack when ready.
             final int lowerCaseFreqInMainDict = dictionaries.hasDict(Dictionary.TYPE_MAIN) ?
-                    dictionaries.getDict(Dictionary.TYPE_MAIN).getFrequency(suggestionLowerCase) :
+                    dictionaries.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) :
                             Dictionary.NOT_A_PROBABILITY;
             if (maxFreq < lowerCaseFreqInMainDict
                     && lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
                 // Use lower cased word as the word can be a distracter of the popular word.
-                secondWord = suggestionLowerCase;
+                secondWord = lowerCasedWord;
             } else {
-                secondWord = suggestion;
+                secondWord = word;
             }
         }
         // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
         // We don't add words with 0-frequency (assuming they would be profanity etc.).
         final boolean isValid = maxFreq > 0;
-        UserHistoryDictionary.addToDictionary(userHistoryDictionary, previousWord, secondWord,
+        UserHistoryDictionary.addToDictionary(userHistoryDictionary, prevWord, secondWord,
                 isValid, timeStampInSeconds);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index e80ee35bd50888760ca90211615e8b127333be68..6a420748cea7952b227776418137d57b973bb029 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -604,7 +604,7 @@ public final class InputLogic {
             if (null != candidate
                     && mSuggestedWords.mSequenceNumber >= mAutoCommitSequenceNumber) {
                 if (candidate.mSourceDict.shouldAutoCommit(candidate)) {
-                    final String[] commitParts = candidate.mWord.split(" ", 2);
+                    final String[] commitParts = candidate.mWord.split(Constants.WORD_SEPARATOR, 2);
                     batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord);
                     promotePhantomSpace(settingsValues);
                     mConnection.commitText(commitParts[0], 0);
@@ -1962,10 +1962,11 @@ public final class InputLogic {
         final CharSequence chosenWordWithSuggestions =
                 SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
                         suggestedWords);
-        mConnection.commitText(chosenWordWithSuggestions, 1);
-        // TODO: we pass 2 here, but would it be better to move this above and pass 1 instead?
+        // Use the 2nd previous word as the previous word because the 1st previous word is the word
+        // to be committed.
         final String prevWord = mConnection.getNthPreviousWord(
                 settingsValues.mSpacingAndPunctuations, 2);
+        mConnection.commitText(chosenWordWithSuggestions, 1);
         // Add the word to the user history dictionary
         performAdditionToUserHistoryDictionary(settingsValues, chosenWord, prevWord);
         // TODO: figure out here if this is an auto-correct or if the best word is actually