Index: /trunk/resources/data/defaultpresets.xml
===================================================================
--- /trunk/resources/data/defaultpresets.xml	(revision 19260)
+++ /trunk/resources/data/defaultpresets.xml	(revision 19261)
@@ -7533,5 +7533,5 @@
             </combo>
             <optional>
-                <text key="inscription" text="Inscription" />
+                <text key="inscription" text="Inscription" multiline="true" />
                 <text key="artist_name" text="Artist Name" />
                 <combo key="material" text="Material" values="concrete,granite,metal,plastic,steel,stone,wood" />
@@ -7547,5 +7547,5 @@
             <reference ref="religious_catholic_christian" />
             <text key="start_date" text="Start date" />
-            <text key="inscription" text="Inscription" />
+            <text key="inscription" text="Inscription" multiline="true" />
         </item> <!-- Wayside Cross -->
         <item name="Wayside Shrine" icon="presets/religion/wayside_shrine.svg" type="node,closedway" preset_name_label="true">
@@ -7558,5 +7558,5 @@
             <combo key="building" text="Building" values="wayside_shrine,yes" values_context="building" />
             <text key="start_date" text="Start date" />
-            <text key="inscription" text="Inscription" />
+            <text key="inscription" text="Inscription" multiline="true" />
         </item> <!-- Wayside Shrine -->
         <item name="Boundary Stone" icon="presets/landmark/boundary_stone.svg" type="node,closedway" preset_name_label="true">
@@ -7566,5 +7566,5 @@
             <optional>
                 <text key="name" text="Name" />
-                <text key="inscription" text="Inscription" />
+                <text key="inscription" text="Inscription" multiline="true" />
             </optional>
             <preset_link preset_name="Boundary Marker" text="Similar but different tags:" />
@@ -7576,5 +7576,5 @@
             <optional>
                 <text key="name" text="Name" />
-                <text key="inscription" text="Inscription" />
+                <text key="inscription" text="Inscription" multiline="true" />
             </optional>
         </item> <!-- Milestone -->
@@ -8965,5 +8965,5 @@
             <optional>
                 <reference ref="name_ref" />
-                <text key="inscription" text="Inscription" />
+                <text key="inscription" text="Inscription" multiline="true" />
                 <combo key="material" text="Material" values="concrete,metal,plastic,steel,stone,wood" />
             </optional>
Index: /trunk/resources/data/tagging-preset.xsd
===================================================================
--- /trunk/resources/data/tagging-preset.xsd	(revision 19260)
+++ /trunk/resources/data/tagging-preset.xsd	(revision 19261)
@@ -649,4 +649,18 @@
             </annotation>
         </attribute>
+        <attribute name="multiline" type="boolean">
+            <annotation>
+                <documentation>
+                    The text is expected to be multiline, and newlines must not be normalized (default is false)
+                </documentation>
+            </annotation>
+        </attribute>
+        <attribute name="normalize" type="boolean">
+            <annotation>
+                <documentation>
+                    This performs normalization of the value by stripping extraneous spaces and consolidating whitespace (default is true for JOSM)
+                </documentation>
+            </annotation>
+        </attribute>
     </attributeGroup>
 
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java	(revision 19260)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java	(revision 19261)
@@ -14,4 +14,5 @@
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Pattern;
 
 import javax.swing.AbstractButton;
@@ -48,4 +49,5 @@
  */
 public class Text extends KeyedItem {
+    private static final Pattern MULTILINE_WHITESPACE_PATTERN = Pattern.compile("[\\s&&[^\n]]+");
 
     private static int auto_increment_selected; // NOSONAR
@@ -241,5 +243,11 @@
         }
 
-        v = Utils.removeWhiteSpaces(v);
+        if (this.normalize) {
+            if (this.multiline) {
+                v = Utils.removeWhiteSpaces(MULTILINE_WHITESPACE_PATTERN, v);
+            } else {
+                v = Utils.removeWhiteSpaces(v);
+            }
+        }
 
         if (!"false".equals(use_last_as_default) || auto_increment != null) {
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/TextItem.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/TextItem.java	(revision 19260)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/TextItem.java	(revision 19261)
@@ -23,4 +23,9 @@
     /** The context used for translating {@link #text} */
     public String text_context; // NOSONAR
+
+    /** {@code true} if the value is a multiline value */
+    public boolean multiline; // NOSONAR
+    /** {@code true} if the value should be normalized */
+    public boolean normalize = true; // NOSONAR
 
     /** The localized version of {@link #text} */
Index: /trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 19260)
+++ /trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 19261)
@@ -821,8 +821,19 @@
      */
     public static String removeWhiteSpaces(String s) {
+        return removeWhiteSpaces(WHITE_SPACES_PATTERN, s);
+    }
+
+    /**
+     * Removes leading, trailing, and multiple inner whitespaces from the given string, to be used as a key or value.
+     * @param s The string
+     * @param whitespaces The regex for whitespaces to remove outside the leading and trailing whitespaces (see {@link #strip(String)})
+     * @return The string without leading, trailing or multiple inner whitespaces
+     * @since 19261
+     */
+    public static String removeWhiteSpaces(Pattern whitespaces, String s) {
         if (isEmpty(s)) {
             return s;
         }
-        return strip(s).replaceAll("\\s+", " ");
+        return whitespaces.matcher(strip(s)).replaceAll(" ");
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/items/TextTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/items/TextTest.java	(revision 19260)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/items/TextTest.java	(revision 19261)
@@ -3,11 +3,27 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JComponent;
 import javax.swing.JPanel;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemTest;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetType;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
+import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.testutils.annotations.Main;
 
@@ -33,3 +49,30 @@
         assertTrue(p.getComponentCount() > 0);
     }
+
+    @org.openstreetmap.josm.testutils.annotations.TaggingPresets
+    @ParameterizedTest
+    @ValueSource(strings = {"\n\n\n\t\r {0}\n\n\n", "{0}"})
+    void testNonRegression24023(String inscription) {
+        // There is a bit of "extra" whitespace in the string (` \n`). It is somewhat deliberate. We probably ought to remove the ` ` at some time.
+        final String expected = "This is a \nsample \ninscription";
+        final String toTest = MessageFormat.format(inscription, expected).replace("sample ", "sample    ");
+        final Collection<TaggingPreset> presets = TaggingPresets.getMatchingPresets(Collections.singleton(TaggingPresetType.NODE), Map.of("historic", "boundary_stone", "inscription", "bar"), false);
+        assertEquals(1, presets.size());
+        final TaggingPreset preset = presets.iterator().next();
+        final Text text = assertInstanceOf(Text.class, preset.data.get(5));
+        final List<Tag> changeCommands = new ArrayList<>(1);
+        final JPanel panel = new JPanel();
+        text.addToPanel(panel, TaggingPresetItemGuiSupport.create(false));
+        JComponent value = assertInstanceOf(JComponent.class, panel.getComponent(1));
+        while (value instanceof JPanel) {
+            value = (JComponent) value.getComponent(0);
+        }
+        final JosmTextField textField = assertInstanceOf(JosmTextField.class, value, "Until we support multiline editing, this should be a text field");
+        textField.setText(toTest);
+        text.addCommands(changeCommands);
+        assertTrue(text.multiline);
+        assertTrue(text.normalize);
+        assertEquals(1, changeCommands.size());
+        assertEquals(expected, changeCommands.get(0).getValue(), "If the only difference is a trailing space was removed, update the test.");
+    }
 }
