diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 817115c3ad17..32b9f1dd0cf0 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -1007,6 +1007,10 @@ public static URL getStaticHelpUrl(StaplerRequest req, Klass c, String suffix if (url != null) return url; url = c.getResource(base + '_' + locale.getLanguage() + ".html"); if (url != null) return url; + if (locale.getLanguage().equals("en")) { + url = c.getResource(base + ".html"); + if (url != null) return url; + } } // default diff --git a/core/src/main/java/org/jenkins/ui/symbol/Symbol.java b/core/src/main/java/org/jenkins/ui/symbol/Symbol.java index 9973acc18da5..6c3fc565ff8d 100644 --- a/core/src/main/java/org/jenkins/ui/symbol/Symbol.java +++ b/core/src/main/java/org/jenkins/ui/symbol/Symbol.java @@ -13,6 +13,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; import jenkins.model.Jenkins; import org.apache.commons.io.IOUtils; @@ -55,13 +56,13 @@ public static String get(@NonNull SymbolRequest request) { .computeIfAbsent(identifier, key -> new ConcurrentHashMap<>()) .computeIfAbsent(name, key -> loadSymbol(identifier, key)); if ((tooltip != null && !tooltip.isBlank()) && (htmlTooltip == null || htmlTooltip.isBlank())) { - symbol = symbol.replaceAll(" locales = Collections.enumeration(Arrays.asList(localeArr)); diff --git a/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java b/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java index 1609e5ff0e3c..49aaa9cd4f52 100644 --- a/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java +++ b/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java @@ -7,6 +7,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.jupiter.api.DisplayName; +import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.RealJenkinsRule; @@ -15,6 +16,22 @@ public class SymbolJenkinsTest { public RealJenkinsRule rjr = new RealJenkinsRule() .addPlugins("plugins/design-library.jpi", "plugins/prism-api.jpi", "plugins/bootstrap5-api.jpi"); + @Test + @Issue("JENKINS-73243") + @DisplayName("When resolving a symbol where the tooltip contains '$' no error is thrown") + public void dollarInToolTipSucceeds() throws Throwable { + rjr.then(SymbolJenkinsTest::_dollarInTooltipSucceeds); + } + + private static void _dollarInTooltipSucceeds(JenkinsRule j) { + String symbol = Symbol.get(new SymbolRequest.Builder() + .withName("add") + .withTooltip("$test") + .build() + ); + assertThat(symbol, containsString("tooltip=\"$test\"")); + } + @Test @DisplayName("When resolving a symbol from a missing plugin, the placeholder is generated instead") public void missingSymbolFromPluginDefaultsToPlaceholder() throws Throwable {