diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 67ca59540c6478559822e77aabfda8cf853b2949..efc5a618b3cfadbcd56797592cb858b455c2d60b 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -192,7 +192,6 @@ public final class Constants {
     public static final int CODE_SPACE = ' ';
     public static final int CODE_PERIOD = '.';
     public static final int CODE_COMMA = ',';
-    public static final int CODE_ARMENIAN_PERIOD = 0x0589;
     public static final int CODE_DASH = '-';
     public static final int CODE_SINGLE_QUOTE = '\'';
     public static final int CODE_DOUBLE_QUOTE = '"';
@@ -208,6 +207,8 @@ public final class Constants {
     public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
     public static final int CODE_CLOSING_CURLY_BRACKET = '}';
     public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
+    public static final int CODE_INVERTED_QUESTION_MARK = 0xBF; // ¿
+    public static final int CODE_INVERTED_EXCLAMATION_MARK = 0xA1; // ¡
 
     /**
      * Special keys code. Must be negative.
diff --git a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
index 702688f93950685f707a0e3d7f667e2164644ca2..9362193323b5b80dc9e20b976b84611aae877896 100644
--- a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
@@ -61,6 +61,22 @@ public final class CapsModeUtils {
                 || WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED == mode;
     }
 
+    /**
+     * Helper method to find out if a code point is starting punctuation.
+     *
+     * This include the Unicode START_PUNCTUATION category, but also some other symbols that are
+     * starting, like the inverted question mark or the double quote.
+     *
+     * @param codePoint the code point
+     * @return true if it's starting punctuation, false otherwise.
+     */
+    private static boolean isStartPunctuation(final int codePoint) {
+        return (codePoint == Constants.CODE_DOUBLE_QUOTE || codePoint == Constants.CODE_SINGLE_QUOTE
+                || codePoint == Constants.CODE_INVERTED_QUESTION_MARK
+                || codePoint == Constants.CODE_INVERTED_EXCLAMATION_MARK
+                || Character.getType(codePoint) == Character.START_PUNCTUATION);
+    }
+
     /**
      * Determine what caps mode should be in effect at the current offset in
      * the text. Only the mode bits set in <var>reqModes</var> will be
@@ -115,8 +131,7 @@ public final class CapsModeUtils {
         } else {
             for (i = cs.length(); i > 0; i--) {
                 final char c = cs.charAt(i - 1);
-                if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE
-                        && Character.getType(c) != Character.START_PUNCTUATION) {
+                if (!isStartPunctuation(c)) {
                     break;
                 }
             }
@@ -210,11 +225,14 @@ public final class CapsModeUtils {
 
         // We found out that we have a period. We need to determine if this is a full stop or
         // otherwise sentence-ending period, or an abbreviation like "e.g.". An abbreviation
-        // looks like (\w\.){2,}
+        // looks like (\w\.){2,}. Moreover, in German, you put periods after digits for dates
+        // and some other things, and in German specifically we need to not go into autocaps after
+        // a whitespace-digits-period sequence.
         // To find out, we will have a simple state machine with the following states :
-        // START, WORD, PERIOD, ABBREVIATION
+        // START, WORD, PERIOD, ABBREVIATION, NUMBER
         // On START : (just before the first period)
         //           letter => WORD
+        //           digit => NUMBER if German; end with caps otherwise
         //           whitespace => end with no caps (it was a stand-alone period)
         //           otherwise => end with caps (several periods/symbols in a row)
         // On WORD : (within the word just before the first period)
@@ -228,6 +246,11 @@ public final class CapsModeUtils {
         //           letter => LETTER
         //           period => PERIOD
         //           otherwise => end with no caps (it was an abbreviation)
+        // On NUMBER : (period immediately preceded by one or more digits)
+        //           digit => NUMBER
+        //           letter => LETTER (promote to word)
+        //           otherwise => end with no caps (it was a whitespace-digits-period sequence,
+        //            or a punctuation-digits-period sequence like "11.11.")
         // "Not an abbreviation" in the above chart essentially covers cases like "...yes.". This
         // should capitalize.
 
@@ -235,6 +258,7 @@ public final class CapsModeUtils {
         final int WORD = 1;
         final int PERIOD = 2;
         final int LETTER = 3;
+        final int NUMBER = 4;
         final int caps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS
                 | TextUtils.CAP_MODE_SENTENCES) & reqModes;
         final int noCaps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
@@ -247,6 +271,8 @@ public final class CapsModeUtils {
                     state = WORD;
                 } else if (Character.isWhitespace(c)) {
                     return noCaps;
+                } else if (Character.isDigit(c) && spacingAndPunctuations.mUsesGermanRules) {
+                    state = NUMBER;
                 } else {
                     return caps;
                 }
@@ -275,6 +301,15 @@ public final class CapsModeUtils {
                 } else {
                     return noCaps;
                 }
+                break;
+            case NUMBER:
+                if (Character.isLetter(c)) {
+                    state = WORD;
+                } else if (Character.isDigit(c)) {
+                    state = NUMBER;
+                } else {
+                    return noCaps;
+                }
             }
         }
         // Here we arrived at the start of the line. This should behave exactly like whitespace.
diff --git a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
index 6fc9df793fbc8f4094335926d9ecd4d452b4bd5e..de5538ed627329e02f93c8f8c49843198b598b56 100644
--- a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
+++ b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
@@ -78,4 +78,35 @@ public class ShiftModeTests extends InputTestsBase {
         runMessages();
         assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted());
     }
+
+    public void testAutoCapsAfterDigitsPeriod() {
+        changeLanguage("en");
+        type("On 22.11.");
+        assertFalse("(English) Auto caps after digits-period", isCapsModeAutoShifted());
+        type(" ");
+        assertTrue("(English) Auto caps after digits-period-whitespace", isCapsModeAutoShifted());
+        mEditText.setText("");
+        changeLanguage("fr");
+        type("Le 22.");
+        assertFalse("(French) Auto caps after digits-period", isCapsModeAutoShifted());
+        type(" ");
+        assertTrue("(French) Auto caps after digits-period-whitespace", isCapsModeAutoShifted());
+        mEditText.setText("");
+        changeLanguage("de");
+        type("Am 22.");
+        assertFalse("(German) Auto caps after digits-period", isCapsModeAutoShifted());
+        type(" ");
+        // For German, no auto-caps in this case
+        assertFalse("(German) Auto caps after digits-period-whitespace", isCapsModeAutoShifted());
+    }
+
+    public void testAutoCapsAfterInvertedMarks() {
+        changeLanguage("es");
+        assertTrue("(Spanish) Auto caps at start", isCapsModeAutoShifted());
+        type("Hey. ¿");
+        assertTrue("(Spanish) Auto caps after inverted what", isCapsModeAutoShifted());
+        mEditText.setText("");
+        type("¡");
+        assertTrue("(Spanish) Auto caps after inverted bang", isCapsModeAutoShifted());
+    }
 }