diff --git a/java/src/com/android/inputmethod/latin/DictionaryStats.java b/java/src/com/android/inputmethod/latin/DictionaryStats.java
index 19769717e53de5912d6b3c44a52ef27eb557672b..46eaff67f7df3ae2dc0d65311541be169bedad3e 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryStats.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryStats.java
@@ -31,6 +31,7 @@ public class DictionaryStats {
     public final String mDictFileName;
     public final long mDictFileSize;
     public final int mContentVersion;
+    public final int mWordCount;
 
     public DictionaryStats(
             @Nonnull final Locale locale,
@@ -43,6 +44,19 @@ public class DictionaryStats {
         mDictFileSize = (dictFile == null || !dictFile.exists()) ? 0 : dictFile.length();
         mDictFileName = dictFileName;
         mContentVersion = contentVersion;
+        mWordCount = -1;
+    }
+
+    public DictionaryStats(
+            @Nonnull final Locale locale,
+            @Nonnull final String dictType,
+            final int wordCount) {
+        mLocale = locale;
+        mDictType = dictType;
+        mDictFileSize = wordCount;
+        mDictFileName = null;
+        mContentVersion = 0;
+        mWordCount = wordCount;
     }
 
     public String getFileSizeString() {
@@ -67,9 +81,14 @@ public class DictionaryStats {
             builder.append(")");
         }
         builder.append(": ");
-        builder.append(mDictFileName);
-        builder.append(" / ");
-        builder.append(getFileSizeString());
+        if (mWordCount > -1) {
+            builder.append(mWordCount);
+            builder.append(" words");
+        } else {
+            builder.append(mDictFileName);
+            builder.append(" / ");
+            builder.append(getFileSizeString());
+        }
         return builder.toString();
     }
 
diff --git a/java/src/com/android/inputmethod/latin/UserDictionaryLookup.java b/java/src/com/android/inputmethod/latin/UserDictionaryLookup.java
index 2569723b0e9a277d93bd4549bb1e5a228641e285..1eed3d79c1d3045cf12fc8c5cae15e4aef94b595 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionaryLookup.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionaryLookup.java
@@ -33,6 +33,7 @@ import com.android.inputmethod.latin.utils.ExecutorUtils;
 import java.io.Closeable;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.ScheduledFuture;
@@ -186,6 +187,8 @@ public class UserDictionaryLookup implements Closeable {
      */
     private volatile ScheduledFuture<?> mReloadFuture;
 
+    private volatile List<DictionaryStats> mDictionaryStats;
+
     /**
      * @param context the context from which to obtain content resolver
      */
@@ -195,11 +198,18 @@ public class UserDictionaryLookup implements Closeable {
         Log.i(mTag, "create()");
 
         mServiceName = serviceName;
+        mDictionaryStats = new ArrayList<DictionaryStats>();
+        mDictionaryStats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER, 0));
+        mDictionaryStats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER_SHORTCUT, 0));
 
         // Obtain a content resolver.
         mResolver = context.getContentResolver();
     }
 
+    public List<DictionaryStats> getDictionaryStats() {
+        return mDictionaryStats;
+    }
+
     public void open() {
         Log.i(mTag, "open()");
 
@@ -506,6 +516,15 @@ public class UserDictionaryLookup implements Closeable {
             }
         }
 
+        List<DictionaryStats> stats = new ArrayList<>();
+        stats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER, dictWords.size()));
+        int numShortcuts = 0;
+        for (HashMap<String, String> shortcuts : shortcutsPerLocale.values()) {
+            numShortcuts += shortcuts.size();
+        }
+        stats.add(new DictionaryStats(ANY_LOCALE, Dictionary.TYPE_USER_SHORTCUT, numShortcuts));
+        mDictionaryStats = stats;
+
         // Atomically replace the copy of mDictWords and mShortcuts.
         mDictWords = dictWords;
         mShortcutsPerLocale = shortcutsPerLocale;
@@ -513,6 +532,7 @@ public class UserDictionaryLookup implements Closeable {
         // Allow other calls to loadUserDictionary to execute now.
         mIsLoading.set(false);
 
-        Log.i(mTag, "loadUserDictionary() : Loaded " + mDictWords.size() + " words");
+        Log.i(mTag, "loadUserDictionary() : Loaded " + mDictWords.size()
+                + " words and " + numShortcuts + " shortcuts");
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/UserDictionaryLookupTest.java b/tests/src/com/android/inputmethod/latin/UserDictionaryLookupTest.java
index d8060f2867299dc0cab045cd486b76323977fdf4..917140ab53167eddbd98f57fc1ea48effba7f709 100644
--- a/tests/src/com/android/inputmethod/latin/UserDictionaryLookupTest.java
+++ b/tests/src/com/android/inputmethod/latin/UserDictionaryLookupTest.java
@@ -309,6 +309,52 @@ public class UserDictionaryLookupTest extends AndroidTestCase {
         lookup.close();
     }
 
+    public void testDictionaryStats() {
+        Log.d(TAG, "testDictionaryStats");
+
+        // Insert "foo" and "bar". Only "foo" has a shortcut.
+        Uri uri = addWord("foo", Locale.GERMANY, 17, "f");
+        addWord("bar", Locale.GERMANY, 17, null);
+
+        // Create the UserDictionaryLookup and wait until it's loaded.
+        UserDictionaryLookup lookup = new UserDictionaryLookup(mContext, ExecutorUtils.SPELLING);
+        lookup.open();
+        while (!lookup.isLoaded()) {
+        }
+
+        // "foo" should match.
+        assertTrue(lookup.isValidWord("foo", Locale.GERMANY));
+
+        // "bar" should match.
+        assertTrue(lookup.isValidWord("bar", Locale.GERMANY));
+
+        // "foo" should have a shortcut.
+        assertEquals("foo", lookup.expandShortcut("f", Locale.GERMANY));
+
+        // Now delete "foo".
+        deleteWord(uri);
+
+        // Wait a little bit before expecting a change. The time we wait should be greater than
+        // UserDictionaryLookup.RELOAD_DELAY_MS.
+        try {
+            Thread.sleep(UserDictionaryLookup.RELOAD_DELAY_MS + 1000);
+        } catch (InterruptedException e) {
+        }
+
+        // Perform lookups again. Reload should have occured.
+        //
+        // "foo" should not match.
+        assertFalse(lookup.isValidWord("foo", Locale.GERMANY));
+
+        // "foo" should not have a shortcut.
+        assertNull(lookup.expandShortcut("f", Locale.GERMANY));
+
+        // "bar" should still match.
+        assertTrue(lookup.isValidWord("bar", Locale.GERMANY));
+
+        lookup.close();
+    }
+
     public void testClose() {
         Log.d(TAG, "testClose");