Index: /trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/Main.java	(revision 7893)
+++ /trunk/src/org/openstreetmap/josm/Main.java	(revision 7894)
@@ -695,9 +695,9 @@
     /**
      * Add a new layer to the map.
-     * 
+     *
      * If no map exists, create one.
-     * 
+     *
      * @param layer the layer
-     * 
+     *
      * @see #addLayer(Layer, ProjectionBounds)
      * @see #addLayer(Layer, ViewportData)
@@ -711,7 +711,7 @@
     /**
      * Add a new layer to the map.
-     * 
+     *
      * If no map exists, create one.
-     * 
+     *
      * @param layer the layer
      * @param bounds the bounds of the layer (target zoom area); can be null, then
@@ -724,7 +724,7 @@
     /**
      * Add a new layer to the map.
-     * 
+     *
      * If no map exists, create one.
-     * 
+     *
      * @param layer the layer
      * @param viewport the viewport to zoom to; can be null, then the viewport
@@ -1236,4 +1236,14 @@
 
     /**
+     * Determines if JOSM currently runs with Java 8 or later.
+     * @return {@code true} if the current JVM is at least Java 8, {@code false} otherwise
+     * @since 7894
+     */
+    public static boolean isJava8orLater() {
+        String version = System.getProperty("java.version");
+        return version != null && !version.matches("^(1\\.)?[7].*");
+    }
+
+    /**
      * Checks that JOSM is at least running with Java 7.
      * @since 7001
Index: /trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 7893)
+++ /trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 7894)
@@ -94,5 +94,5 @@
      */
     private File cacheDir = null;
-    
+
     /**
      * Internal storage for the user data directory.
@@ -1375,8 +1375,8 @@
         if(getBoolean("prefer.ipv6", false)) {
             // never set this to false, only true!
-            updateSystemProperty("java.net.preferIPv6Addresses", "true");
-        }
-        updateSystemProperty("http.agent", Version.getInstance().getAgentString());
-        updateSystemProperty("user.language", get("language"));
+            Utils.updateSystemProperty("java.net.preferIPv6Addresses", "true");
+        }
+        Utils.updateSystemProperty("http.agent", Version.getInstance().getAgentString());
+        Utils.updateSystemProperty("user.language", get("language"));
         // Workaround to fix a Java bug.
         // Force AWT toolkit to update its internal preferences (fix #3645).
@@ -1392,5 +1392,5 @@
         // See http://stackoverflow.com/q/7615645/2257172 and #9875
         if (getBoolean("jdk.tls.disableSNIExtension", true)) {
-            updateSystemProperty("jsse.enableSNIExtension", "false");
+            Utils.updateSystemProperty("jsse.enableSNIExtension", "false");
         }
         // Workaround to fix another Java bug
@@ -1399,26 +1399,6 @@
         // and https://bugs.openjdk.java.net/browse/JDK-6923200
         if (getBoolean("jdk.Arrays.useLegacyMergeSort", !Version.getInstance().isLocalBuild())) {
-            updateSystemProperty("java.util.Arrays.useLegacyMergeSort", "true");
-        }
-    }
-
-    /**
-     * Updates a given system property.
-     * @param key The property key
-     * @param value The property value
-     * @return the previous value of the system property, or {@code null} if it did not have one.
-     * @since 6851
-     */
-    public static String updateSystemProperty(String key, String value) {
-        if (value != null) {
-            String old = System.setProperty(key, value);
-            if (!key.toLowerCase().contains("password")) {
-                Main.debug("System property '"+key+"' set to '"+value+"'. Old value was '"+old+"'");
-            } else {
-                Main.debug("System property '"+key+"' changed.");
-            }
-            return old;
-        }
-        return null;
+            Utils.updateSystemProperty("java.util.Arrays.useLegacyMergeSort", "true");
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 7893)
+++ /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 7894)
@@ -46,5 +46,4 @@
 import org.openstreetmap.josm.data.AutosaveTask;
 import org.openstreetmap.josm.data.CustomConfigurator;
-import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.gui.download.DownloadDialog;
@@ -348,5 +347,5 @@
             logLevel = 5;
             // Enable debug in OAuth signpost via system preference, but only at trace level
-            Preferences.updateSystemProperty("debug", "true");
+            Utils.updateSystemProperty("debug", "true");
             Main.info(tr("Enabled detailed debug level (trace)"));
         }
Index: /trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControlHttpsServer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControlHttpsServer.java	(revision 7893)
+++ /trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControlHttpsServer.java	(revision 7894)
@@ -146,6 +146,5 @@
         // https://bugs.openjdk.java.net/browse/JDK-8040820
         // https://bugs.openjdk.java.net/browse/JDK-7198416
-        String version = System.getProperty("java.version");
-        if (version == null || version.matches("^(1\\.)?[7].*")) {
+        if (!Main.isJava8orLater()) {
             // Java 7 code. To remove with Java 8 migration
             info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
Index: /trunk/src/org/openstreetmap/josm/tools/I18n.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/I18n.java	(revision 7893)
+++ /trunk/src/org/openstreetmap/josm/tools/I18n.java	(revision 7894)
@@ -39,7 +39,40 @@
     }
 
+    /**
+     * Enumeration of possible plural modes.
+     * See <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html">CLDR</a>
+     * for a complete list.
+     * @see #pluralEval
+     */
     private enum PluralMode {
-        MODE_NOTONE, MODE_NONE, MODE_GREATERONE,
-        MODE_CS/*, MODE_AR*/, MODE_PL/*, MODE_RO*/, MODE_RU, MODE_SK/*, MODE_SL*/}
+        /** Plural = Not 1. This is the default for many languages, including English: 1 day, but 0 days or 2 days. */
+        MODE_NOTONE,
+        /** No plural. Mainly for Asian languages (Indonesian, Chinese, Japanese, ...) */
+        MODE_NONE,
+        /** Plural = Greater than 1. For some latin languages (French, Brazilian Portuguese) */
+        MODE_GREATERONE,
+        /* Special mode for
+         * <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ar">Arabic</a>.*
+        MODE_AR,*/
+        /** Special mode for
+         * <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#cs">Czech</a>. */
+        MODE_CS,
+        /** Special mode for
+         * <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#pl">Polish</a>. */
+        MODE_PL,
+        /* Special mode for
+         * <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ro">Romanian</a>.*
+        MODE_RO,*/
+        /** Special mode for
+         * <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ru">Russian</a>. */
+        MODE_RU,
+        /** Special mode for
+         * <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#sk">Slovak</a>. */
+        MODE_SK,
+        /* Special mode for
+         * <a href="http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#sl">Slovenian</a>.*
+        MODE_SL,*/
+    }
+
     private static PluralMode pluralMode = PluralMode.MODE_NOTONE; /* english default */
     private static String loadedCode = "en";
@@ -353,4 +386,10 @@
      */
     public static void init() {
+        // Enable CLDR locale provider on Java 8 to get additional languages, such as Khmer.
+        // http://docs.oracle.com/javase/8/docs/technotes/guides/intl/enhancements.8.html#cldr
+        // This can be removed after we switch to a minimal version of Java that enables CLDR by default
+        // or includes all languages we need in the JRE. See http://openjdk.java.net/jeps/8043554 for Java 9
+        Utils.updateSystemProperty("java.locale.providers", "JRE,CLDR");
+
         //languages.put("ar", PluralMode.MODE_AR);
         languages.put("bg", PluralMode.MODE_NOTONE);
@@ -374,4 +413,8 @@
         languages.put("it", PluralMode.MODE_NOTONE);
         languages.put("ja", PluralMode.MODE_NONE);
+        if (Main.isJava8orLater()) {
+            // Java 8 and later code
+            languages.put("km", PluralMode.MODE_NONE);
+        }
         //languages.put("nb", PluralMode.MODE_NOTONE);
         languages.put("nl", PluralMode.MODE_NOTONE);
@@ -649,5 +692,5 @@
         case MODE_NOTONE: /* bg, da, de, el, en, en_GB, es, et, eu, fi, gl, is, it, iw_IL, nb, nl, sv */
             return ((n != 1) ? 1 : 0);
-        case MODE_NONE: /* ja, tr, zh_CN, zh_TW */
+        case MODE_NONE: /* id, ja, km, tr, zh_CN, zh_TW */
             return 0;
         case MODE_GREATERONE: /* fr, pt_BR */
Index: /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java	(revision 7893)
+++ /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java	(revision 7894)
@@ -19,5 +19,4 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.OpenFileAction.OpenFileTask;
-import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.xml.sax.SAXException;
@@ -37,5 +36,5 @@
         // And will not work when one of the system independent LAFs is used.
         // They just insist on painting themselves...
-        Preferences.updateSystemProperty("apple.laf.useScreenMenuBar", "true");
+        Utils.updateSystemProperty("apple.laf.useScreenMenuBar", "true");
         migrateOldDirectory();
     }
Index: /trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 7893)
+++ /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 7894)
@@ -1144,3 +1144,23 @@
         return new Pair<>(noThreads, pool);
     }
+
+    /**
+     * Updates a given system property.
+     * @param key The property key
+     * @param value The property value
+     * @return the previous value of the system property, or {@code null} if it did not have one.
+     * @since 7894
+     */
+    public static String updateSystemProperty(String key, String value) {
+        if (value != null) {
+            String old = System.setProperty(key, value);
+            if (!key.toLowerCase().contains("password")) {
+                Main.debug("System property '"+key+"' set to '"+value+"'. Old value was '"+old+"'");
+            } else {
+                Main.debug("System property '"+key+"' changed.");
+            }
+            return old;
+        }
+        return null;
+    }
 }
