diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 60ac1ba48bfb8043097e0b5f224b6672c218df86..32f905628a7e37591a0406ea5042c183a74cea7d 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -231,16 +231,17 @@ public final class BinaryDictionary extends Dictionary {
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
-            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+            final float[] inOutLanguageWeight) {
         return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords,
-                additionalFeaturesOptions, 0 /* sessionId */);
+                additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight);
     }
 
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
             final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
-            final int sessionId) {
+            final int sessionId, final float[] inOutLanguageWeight) {
         if (!isValidDictionary()) return null;
 
         Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE);
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index e045248439ddf293428adf41c59c5fb136779a05..0742fbde91acc8f872f344891eda1cf9018a08b0 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
  */
 public abstract class Dictionary {
     public static final int NOT_A_PROBABILITY = -1;
+    public static final float NOT_A_LANGUAGE_WEIGHT = -1.0f;
 
     // The following types do not actually come from real dictionary instances, so we create
     // corresponding instances.
@@ -70,22 +71,26 @@ public abstract class Dictionary {
      * @param proximityInfo the object for key proximity. May be ignored by some implementations.
      * @param blockOffensiveWords whether to block potentially offensive words
      * @param additionalFeaturesOptions options about additional features used for the suggestion.
+     * @param inOutLanguageWeight the language weight used for generating suggestions.
+     * inOutLanguageWeight is a float array that has only one element. This can be updated when the
+     * different language weight is used.
      * @return the list of suggestions (possibly null if none)
      */
     // TODO: pass more context than just the previous word, to enable better suggestions (n-gram
     // and more)
     abstract public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
-            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions);
+            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+            final float[] inOutLanguageWeight);
 
     // The default implementation of this method ignores sessionId.
     // Subclasses that want to use sessionId need to override this method.
     public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
             final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
-            final int sessionId) {
+            final int sessionId, final float[] inOutLanguageWeight) {
         return getSuggestions(composer, prevWord, proximityInfo, blockOffensiveWords,
-                additionalFeaturesOptions);
+                additionalFeaturesOptions, inOutLanguageWeight);
     }
 
     /**
@@ -159,7 +164,8 @@ public abstract class Dictionary {
         @Override
         public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
                 final String prevWord, final ProximityInfo proximityInfo,
-                final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+                final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+                final float[] inOutLanguageWeight) {
             return null;
         }
 
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index bf075140ebf3e9a48caef9f00fcf75f1521435cc..16173fffc0354952dcbf3e22f2d3e24efe6df5fc 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -58,18 +58,21 @@ public final class DictionaryCollection extends Dictionary {
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
-            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+            final float[] inOutLanguageWeight) {
         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).getSuggestions(composer,
-                prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions);
+                prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions,
+                inOutLanguageWeight);
         if (null == suggestions) suggestions = CollectionUtils.newArrayList();
         final int length = dictionaries.size();
         for (int i = 1; i < length; ++ i) {
             final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(composer,
-                    prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions);
+                    prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions,
+                    inOutLanguageWeight);
             if (null != sugg) suggestions.addAll(sugg);
         }
         return suggestions;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index 9c6aa552c690090af18ab865fe809c1b92d5ba7e..7cb218fbe45c993b5015050ea690c133a22c5861 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -461,12 +461,14 @@ public class DictionaryFacilitatorForSuggest {
         final Map<String, Dictionary> dictMap = dictionaries.mDictMap;
         final SuggestionResults suggestionResults =
                 new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS);
+        final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
         for (final String dictType : dictTypesOrderedToGetSuggestion) {
             final Dictionary dictionary = dictMap.get(dictType);
             if (null == dictionary) continue;
             final ArrayList<SuggestedWordInfo> dictionarySuggestions =
                     dictionary.getSuggestionsWithSessionId(composer, prevWord, proximityInfo,
-                            blockOffensiveWords, additionalFeaturesOptions, sessionId);
+                            blockOffensiveWords, additionalFeaturesOptions, sessionId,
+                            languageWeight);
             if (null == dictionarySuggestions) continue;
             suggestionResults.addAll(dictionarySuggestions);
             if (null != rawSuggestions) {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 92b53545814e47d12d79c32ba6ea606af8fb02e8..aea4811a9709889c02c0d28eb45ca7efcaa44274 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -387,7 +387,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
             final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
-            final int sessionId) {
+            final int sessionId, final float[] inOutLanguageWeight) {
         reloadDictionaryIfRequired();
         if (processingLargeTask()) {
             return null;
@@ -404,7 +404,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
                 final ArrayList<SuggestedWordInfo> binarySuggestion =
                         mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord,
                                 proximityInfo, blockOffensiveWords, additionalFeaturesOptions,
-                                sessionId);
+                                sessionId, inOutLanguageWeight);
                 holder.set(binarySuggestion);
                 if (mBinaryDictionary.isCorrupted()) {
                     removeBinaryDictionaryLocked();
@@ -417,9 +417,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
-            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+            final float[] inOutLanguageWeight) {
         return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords,
-                additionalFeaturesOptions, 0 /* sessionId */);
+                additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
index 68505ce381fb9091ef869e599e5e9e9731cb48df..9f61d6c37f46dcbdfbec8f22f8707f4b9ec0bd3d 100644
--- a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
@@ -51,20 +51,21 @@ public final class ReadOnlyBinaryDictionary extends Dictionary {
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
-            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+            final float[] inOutLanguageWeight) {
         return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords,
-                additionalFeaturesOptions, 0 /* sessionId */);
+                additionalFeaturesOptions, 0 /* sessionId */, inOutLanguageWeight);
     }
 
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
             final String prevWord, final ProximityInfo proximityInfo,
             final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
-            final int sessionId) {
+            final int sessionId, final float[] inOutLanguageWeight) {
         if (mLock.readLock().tryLock()) {
             try {
                 return mBinaryDictionary.getSuggestions(composer, prevWord, proximityInfo,
-                        blockOffensiveWords, additionalFeaturesOptions);
+                        blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight);
             } finally {
                 mLock.readLock().unlock();
             }
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 9c095e4b1e62372f60f18a321eae2dbd09d498b0..c24ee4033476ae09e7beaea499ac219db60b3b5f 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -34,10 +34,11 @@ public final class SynchronouslyLoadedContactsBinaryDictionary extends ContactsB
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes,
             final String prevWordForBigrams, final ProximityInfo proximityInfo,
-            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+            final float[] inOutLanguageWeight) {
         synchronized (mLock) {
             return super.getSuggestions(codes, prevWordForBigrams, proximityInfo,
-                    blockOffensiveWords, additionalFeaturesOptions);
+                    blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
index 801fb5b894687ab868ac7ca87f8c22f6f1c36ea7..1d29d7ad0f04654a788066bff3bba2ba7ded4481 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -39,10 +39,11 @@ public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDic
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer codes,
             final String prevWordForBigrams, final ProximityInfo proximityInfo,
-            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+            final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+            final float[] inOutLanguageWeight) {
         synchronized (mLock) {
             return super.getSuggestions(codes, prevWordForBigrams, proximityInfo,
-                    blockOffensiveWords, additionalFeaturesOptions);
+                    blockOffensiveWords, additionalFeaturesOptions, inOutLanguageWeight);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index 3947019ca490d2f8db78d3b81205fa8aa9dbe146..69d09275113e9735327987bdf19f2577fb5811ac 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -327,7 +327,8 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
                 final ArrayList<SuggestedWordInfo> suggestions =
                         dictInfo.mDictionary.getSuggestions(composer, prevWord,
                                 dictInfo.getProximityInfo(), true /* blockOffensiveWords */,
-                                null /* additionalFeaturesOptions */);
+                                null /* additionalFeaturesOptions */,
+                                null /* inOutLanguageWeight */);
                 if (suggestions != null) {
                     for (final SuggestedWordInfo suggestion : suggestions) {
                         final String suggestionStr = suggestion.mWord;
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
index b7a5a4026c1b6fb38f2ebbd95162870d53b5b818..c99264347ebe2b37bc2913c82e5d76b03781e493 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/DictionaryPool.java
@@ -53,7 +53,8 @@ public final class DictionaryPool extends LinkedBlockingQueue<DictAndKeyboard> {
                 @Override
                 public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
                         final String prevWord, final ProximityInfo proximityInfo,
-                        final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) {
+                        final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
+                        final float[] inOutLanguageWeight) {
                     return noSuggestions;
                 }
                 @Override