Index: /trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Feature.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Feature.java	(revision 17913)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Feature.java	(revision 17914)
@@ -6,4 +6,5 @@
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.openstreetmap.josm.data.osm.TagMap;
@@ -111,5 +112,5 @@
             if (value instanceof Double || value instanceof Float) {
                 // reset grouping if the instance is a singleton
-                final NumberFormat numberFormat = NumberFormat.getNumberInstance();
+                final NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.ROOT);
                 final boolean grouping = numberFormat.isGroupingUsed();
                 try {
Index: /trunk/test/unit/org/openstreetmap/josm/data/imagery/vectortile/mapbox/FeatureTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/imagery/vectortile/mapbox/FeatureTest.java	(revision 17913)
+++ /trunk/test/unit/org/openstreetmap/josm/data/imagery/vectortile/mapbox/FeatureTest.java	(revision 17914)
@@ -13,7 +13,10 @@
 
 import java.text.NumberFormat;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 import org.junit.jupiter.api.Test;
+import org.openstreetmap.josm.testutils.annotations.I18n;
 
 /**
@@ -51,5 +54,5 @@
         // 49 74 24 00 == 1_000_000f
         // 3f 80 00 00 == 1f
-        byte[] newBytes = new byte[] {0x22, 0x09, 0x15, 0x00, 0x24, 0x74, 0x49};
+        byte[] newBytes = new byte[] {0x22, 0x05, 0x15, 0x00, 0x24, 0x74, 0x49};
         byte[] copyBytes = Arrays.copyOf(getSimpleFeatureLayerBytes(), getSimpleFeatureLayerBytes().length + newBytes.length - 4);
         // Change last few bytes
@@ -78,4 +81,43 @@
         checkDefaultGeometry(feature);
         assertEquals("1000000", feature.getTags().get("a"));
+    }
+
+    /**
+     * Non-regression test for #20933 (Russian)
+     * @see #testNumberGroupingDecimalEn()
+     */
+    @I18n("ru")
+    @Test
+    void testNumberGroupingDecimalRu() {
+        testNumberGroupingDecimal();
+    }
+
+    /**
+     * Non-regression test for #20933 (English)
+     * @see #testNumberGroupingDecimalRu()
+     */
+    @I18n("en")
+    @Test
+    void testNumberGroupingDecimalEn() {
+        testNumberGroupingDecimal();
+    }
+
+    /**
+     * Common parts for non-regression tests for #20933
+     * @see #testNumberGroupingDecimalEn()
+     * @see #testNumberGroupingDecimalRu()
+     */
+    private void testNumberGroupingDecimal() {
+        byte[] newBytes = new byte[] {0x22, 0x09, 0x19, -45, 0x4D, 0x62, 0x10, 0x58, -71, 0x67, 0x40};
+        byte[] copyBytes = Arrays.copyOf(getSimpleFeatureLayerBytes(), getSimpleFeatureLayerBytes().length + newBytes.length - 4);
+        // Change last few bytes
+        System.arraycopy(newBytes, 0, copyBytes, 25, newBytes.length);
+        // Update the length of the record
+        copyBytes[1] = (byte) (copyBytes[1] + newBytes.length - 4);
+        Layer layer = assertDoesNotThrow(() -> getLayer(copyBytes));
+        layer.getKey(0);
+        List<Feature> features = new ArrayList<>(layer.getFeatures());
+        assertEquals(1, features.size());
+        assertEquals("189.792", features.get(0).getTags().get("a"));
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/I18n.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/I18n.java	(revision 17914)
+++ /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/I18n.java	(revision 17914)
@@ -0,0 +1,51 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.testutils.annotations;
+
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.platform.commons.support.AnnotationSupport;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Enables the i18n module for this test.
+ * @author Taylor Smock
+ * @see org.openstreetmap.josm.testutils.JOSMTestRules#i18n(String)
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@ExtendWith(I18n.I18nExtension.class)
+public @interface I18n {
+
+    /**
+     * Get the language to use for i18n
+     * @return The language (default "en").
+     */
+    String value() default "en";
+
+    /**
+     * Enables the i18n module for this test.
+     * @author Taylor Smock
+     * @see org.openstreetmap.josm.testutils.JOSMTestRules#i18n(String)
+     */
+    class I18nExtension implements AfterEachCallback, BeforeEachCallback {
+        @Override
+        public void beforeEach(ExtensionContext context) {
+            String language = AnnotationSupport.findAnnotation(context.getElement(), I18n.class).map(I18n::value).orElse("en");
+            org.openstreetmap.josm.tools.I18n.set(language);
+        }
+
+        @Override
+        public void afterEach(ExtensionContext context) {
+            org.openstreetmap.josm.tools.I18n.set("en");
+            org.openstreetmap.josm.tools.I18n.set(org.openstreetmap.josm.tools.I18n.getOriginalLocale().getLanguage());
+        }
+    }
+}
