diff --git a/changelog.html b/changelog.html
index 787e0eb3bf9e560c09f67571efa735675dc4f686..db5bbe9053ae4edb862d64429609535b75edc0b6 100644
--- a/changelog.html
+++ b/changelog.html
@@ -72,6 +72,9 @@ Upcoming changes
+ Defined a mechanism to replace some of the key UI text.
+ (issue 8579)
diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java
index d12d1d3859e9eb1d730f4028499df86fc295a5a7..a3aff920f53748992207155cf7fb3bea9a804611 100644
--- a/core/src/main/java/hudson/model/AbstractProject.java
+++ b/core/src/main/java/hudson/model/AbstractProject.java
@@ -70,6 +70,8 @@ import hudson.tasks.Publisher;
import hudson.triggers.SCMTrigger;
import hudson.triggers.Trigger;
import hudson.triggers.TriggerDescriptor;
+import hudson.util.AlternativeUiTextProvider;
+import hudson.util.AlternativeUiTextProvider.Message;
import hudson.util.DescribableList;
import hudson.util.EditDistance;
import hudson.util.FormValidation;
@@ -353,6 +355,15 @@ public abstract class AbstractProject,R extends A
return Messages.AbstractProject_Pronoun();
}
+ /**
+ * Gets the human readable display name to be rendered in the "Build Now" link.
+ *
+ * @since 1.401
+ */
+ public String getBuildNowText() {
+ return AlternativeUiTextProvider.get(BUILD_NOW_TEXT,this,Messages.AbstractProject_BuildNow());
+ }
+
/**
* Returns the root project value.
*
@@ -1910,6 +1921,8 @@ public abstract class AbstractProject
,R extends A
*/
public static final Permission ABORT = BUILD;
+ public static final Message BUILD_NOW_TEXT = new Message();
+
/**
* Used for CLI binding.
*/
diff --git a/core/src/main/java/hudson/util/AlternativeUiTextProvider.java b/core/src/main/java/hudson/util/AlternativeUiTextProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..daf323c64e6fa52bc5aeb79ce2262d8b5df2b13b
--- /dev/null
+++ b/core/src/main/java/hudson/util/AlternativeUiTextProvider.java
@@ -0,0 +1,109 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2011, CloudBees, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package hudson.util;
+
+import hudson.Extension;
+import hudson.ExtensionList;
+import hudson.ExtensionPoint;
+import hudson.model.AbstractProject;
+import hudson.model.Hudson;
+
+/**
+ * Provides the alternative text to be rendered in the UI.
+ *
+ *
+ * In a few limited places in Jenkins, we want to provide an ability for plugins to replace
+ * the text to be shown in the UI. Since each such case is rather trivial and can't justify
+ * its own extension point, we consolidate all such use cases into a single extension point.
+ *
+ *
+ * Each such overridable UI text can have a context, which represents some information
+ * that enables the {@link AlternativeUiTextProvider} to make intelligent decision. This
+ * is normally some kind of a model object, such as {@link AbstractProject}.
+ *
+ *
+ * To define a new UI text that can be overridable by {@link AlternativeUiTextProvider},
+ * define a constant of {@link Message} (parameterized with the context object type),
+ * then call {@link #get(Message, Object)} to obtain a text.
+ *
+ *
+ * To define an implementation that overrides text, define a subtype and put @{@link Extension} on it.
+ * See {@link AbstractProject#getBuildNowText()} as an example.
+ *
+ * @author Kohsuke Kawaguchi
+ * @since 1.401
+ */
+public abstract class AlternativeUiTextProvider implements ExtensionPoint {
+ /**
+ * Provides an opportunity to override the message text.
+ *
+ * @param text
+ * Always non-null. Caller should pass in a {@link Message} constant that
+ * represents the text that we are being considered.
+ * @param context
+ * Context object. See class javadoc above.
+ */
+ public abstract String getText(Message text, T context);
+
+ /**
+ * All the registered extension point instances.
+ */
+ public static ExtensionList all() {
+ return Hudson.getInstance().getExtensionList(AlternativeUiTextProvider.class);
+ }
+
+ public static String get(Message text, T context, String defaultValue) {
+ String s = get(text,context);
+ return s!=null ? s : defaultValue;
+ }
+
+ /**
+ * Consults all the existing {@link AlternativeUiTextProvider} and return an override, if any,
+ * or null.
+ */
+ public static String get(Message text, T context) {
+ for (AlternativeUiTextProvider p : all()) {
+ String s = p.getText(text, context);
+ if (s!=null)
+ return s;
+ }
+ return null;
+ }
+
+ /**
+ * @param
+ * Context object type. Use {@link Void} to indicate that there's no context.
+ */
+ public static class Message {
+ // decided not to retain T as Class so that we can have Message>, for example.
+
+ /**
+ * Assists pattern matching in the {@link AlternativeUiTextProvider} implementation.
+ */
+ @SuppressWarnings({"unchecked"})
+ public T cast(Object context) {
+ return (T)context;
+ }
+ }
+}
diff --git a/core/src/main/resources/hudson/model/AbstractProject/sidepanel.jelly b/core/src/main/resources/hudson/model/AbstractProject/sidepanel.jelly
index 91e725382f33e8ade0defa3eea1807e4c0ecb99c..245910626ad84b950fc5b57d1d4ae4890414afff 100644
--- a/core/src/main/resources/hudson/model/AbstractProject/sidepanel.jelly
+++ b/core/src/main/resources/hudson/model/AbstractProject/sidepanel.jelly
@@ -42,7 +42,7 @@ THE SOFTWARE.
-