This is an automated email from the ASF dual-hosted git repository.

michaelo pushed a commit to branch use-renderer
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git

commit 3a37c640207dc62e90e012c78db0fae6e2e93226
Author: Michael Osipov <micha...@apache.org>
AuthorDate: Mon May 1 16:53:06 2023 +0200

    [SUREFIRE-2160] Replace LocalizedProperties with (Custom)I18N approach from 
MPIR
---
 .../report/AbstractSurefireReportMojo.java         | 279 +++++++++++++++++++--
 .../surefire/report/FailsafeReportMojo.java        |  64 +----
 .../surefire/report/LocalizedProperties.java       | 100 --------
 .../surefire/report/SurefireReportMojo.java        |  64 +----
 .../surefire/report/SurefireReportRenderer.java    |  92 ++++---
 .../src/main/resources/surefire-report.properties  |   7 +-
 .../main/resources/surefire-report_de.properties   |   9 +-
 .../main/resources/surefire-report_sv.properties   |   7 +-
 .../plugins/surefire/report/Surefire597Test.java   |  11 +-
 .../surefire/report/SurefireReportMojoTest.java    |   4 -
 .../resources/unit/surefire-1183/plugin-config.xml |   3 +-
 .../src/site/custom/surefire-report.properties     |  22 ++
 .../Surefire1490ReportTitleDescriptionIT.java      |  16 +-
 .../jiras/Surefire260TestWithIdenticalNamesIT.java |   1 -
 .../src/site/custom/surefire-report.properties     |  25 ++
 15 files changed, 389 insertions(+), 315 deletions(-)

diff --git 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
index 44f107b01..9a192567c 100644
--- 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
+++ 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java
@@ -19,18 +19,33 @@
 package org.apache.maven.plugins.surefire.report;
 
 import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
 
 import org.apache.maven.model.ReportPlugin;
 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
+import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.reporting.AbstractMavenReport;
 import org.apache.maven.reporting.MavenReportException;
+import org.apache.maven.settings.Settings;
 import org.apache.maven.shared.utils.PathTool;
+import org.codehaus.plexus.i18n.I18N;
+import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
+import org.codehaus.plexus.interpolation.InterpolationException;
+import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
+import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
+import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
 
 import static java.util.Collections.addAll;
 import static 
org.apache.maven.plugins.surefire.report.SurefireReportParser.hasReportFiles;
@@ -87,6 +102,27 @@ public abstract class AbstractSurefireReportMojo extends 
AbstractMavenReport {
     @Parameter(defaultValue = "false", property = "aggregate")
     private boolean aggregate;
 
+    /**
+     * The current user system settings for use in Maven.
+     */
+    @Parameter(defaultValue = "${settings}", readonly = true, required = true)
+    private Settings settings;
+
+    /**
+     * Path for a custom bundle instead of using the default one. <br>
+     * Using this field, you could change the texts in the generated reports.
+     *
+     * @since 3.1.0
+     */
+    @Parameter(defaultValue = "src/site/custom/surefire-report.properties")
+    private String customBundle;
+
+    /**
+     * Internationalization component
+     */
+    @Component
+    private I18N i18n;
+
     private List<File> resolvedReportsDirectories;
 
     /**
@@ -109,14 +145,6 @@ public abstract class AbstractSurefireReportMojo extends 
AbstractMavenReport {
         return false;
     }
 
-    public abstract void setTitle(String title);
-
-    public abstract String getTitle();
-
-    public abstract void setDescription(String description);
-
-    public abstract String getDescription();
-
     /**
      * {@inheritDoc}
      */
@@ -128,8 +156,9 @@ public abstract class AbstractSurefireReportMojo extends 
AbstractMavenReport {
 
         SurefireReportRenderer r = new SurefireReportRenderer(
                 getSink(),
+                getI18N(locale),
+                getI18Nsection(),
                 locale,
-                getBundle(locale),
                 getConsoleLogger(),
                 showSuccess,
                 getReportsDirectories(),
@@ -270,19 +299,44 @@ public abstract class AbstractSurefireReportMojo extends 
AbstractMavenReport {
     }
 
     /**
-     * {@inheritDoc}
+     * @param locale The locale
+     * @param key The key to search for
+     * @return The text appropriate for the locale.
      */
-    @Override
-    public String getName(Locale locale) {
-        return getBundle(locale).getReportName();
+    protected String getI18nString(Locale locale, String key) {
+        return getI18N(locale).getString("surefire-report", locale, "report." 
+ getI18Nsection() + '.' + key);
     }
+    /**
+     * @param locale The local.
+     * @return I18N for the locale
+     */
+    protected I18N getI18N(Locale locale) {
+        if (customBundle != null) {
+            File customBundleFile = new File(customBundle);
+            if (customBundleFile.isFile() && 
customBundleFile.getName().endsWith(".properties")) {
+                if (!i18n.getClass().isAssignableFrom(CustomI18N.class)
+                        || 
!i18n.getDefaultLanguage().equals(locale.getLanguage())) {
+                    // first load
+                    i18n = new CustomI18N(project, settings, customBundleFile, 
locale, i18n);
+                }
+            }
+        }
 
+        return i18n;
+    }
     /**
-     * {@inheritDoc}
+     * @return The according string for the section.
      */
-    @Override
+    protected abstract String getI18Nsection();
+
+    /** {@inheritDoc} */
+    public String getName(Locale locale) {
+        return getI18nString(locale, "name");
+    }
+
+    /** {@inheritDoc} */
     public String getDescription(Locale locale) {
-        return getBundle(locale).getReportDescription();
+        return getI18nString(locale, "description");
     }
 
     /**
@@ -291,18 +345,199 @@ public abstract class AbstractSurefireReportMojo extends 
AbstractMavenReport {
     @Override
     public abstract String getOutputName();
 
-    protected abstract LocalizedProperties getBundle(Locale locale, 
ClassLoader resourceBundleClassLoader);
-
     protected final ConsoleLogger getConsoleLogger() {
         return new PluginConsoleLogger(getLog());
     }
 
-    final LocalizedProperties getBundle(Locale locale) {
-        return getBundle(locale, getClass().getClassLoader());
-    }
-
     @Override
     protected MavenProject getProject() {
         return project;
     }
+
+    // TODO Review, especially Locale.getDefault()
+    private static class CustomI18N implements I18N {
+        private final MavenProject project;
+
+        private final Settings settings;
+
+        private final String bundleName;
+
+        private final Locale locale;
+
+        private final I18N i18nOriginal;
+
+        private ResourceBundle bundle;
+
+        private static final Object[] NO_ARGS = new Object[0];
+
+        CustomI18N(MavenProject project, Settings settings, File 
customBundleFile, Locale locale, I18N i18nOriginal) {
+            super();
+            this.project = project;
+            this.settings = settings;
+            this.locale = locale;
+            this.i18nOriginal = i18nOriginal;
+            this.bundleName = customBundleFile
+                    .getName()
+                    .substring(0, 
customBundleFile.getName().indexOf(".properties"));
+
+            URLClassLoader classLoader = null;
+            try {
+                classLoader = new URLClassLoader(
+                        new URL[] 
{customBundleFile.getParentFile().toURI().toURL()}, null);
+            } catch (MalformedURLException e) {
+                // could not happen.
+            }
+
+            this.bundle = ResourceBundle.getBundle(this.bundleName, locale, 
classLoader);
+            if 
(!this.bundle.getLocale().getLanguage().equals(locale.getLanguage())) {
+                this.bundle = ResourceBundle.getBundle(this.bundleName, 
Locale.getDefault(), classLoader);
+            }
+        }
+
+        /** {@inheritDoc} */
+        public String getDefaultLanguage() {
+            return locale.getLanguage();
+        }
+
+        /** {@inheritDoc} */
+        public String getDefaultCountry() {
+            return locale.getCountry();
+        }
+
+        /** {@inheritDoc} */
+        public String getDefaultBundleName() {
+            return bundleName;
+        }
+
+        /** {@inheritDoc} */
+        public String[] getBundleNames() {
+            return new String[] {bundleName};
+        }
+
+        /** {@inheritDoc} */
+        public ResourceBundle getBundle() {
+            return bundle;
+        }
+
+        /** {@inheritDoc} */
+        public ResourceBundle getBundle(String bundleName) {
+            return bundle;
+        }
+
+        /** {@inheritDoc} */
+        public ResourceBundle getBundle(String bundleName, String 
languageHeader) {
+            return bundle;
+        }
+
+        /** {@inheritDoc} */
+        public ResourceBundle getBundle(String bundleName, Locale locale) {
+            return bundle;
+        }
+
+        /** {@inheritDoc} */
+        public Locale getLocale(String languageHeader) {
+            return new Locale(languageHeader);
+        }
+
+        /** {@inheritDoc} */
+        public String getString(String key) {
+            return getString(bundleName, locale, key);
+        }
+
+        /** {@inheritDoc} */
+        public String getString(String key, Locale locale) {
+            return getString(bundleName, locale, key);
+        }
+
+        /** {@inheritDoc} */
+        public String getString(String bundleName, Locale locale, String key) {
+            String value;
+
+            if (locale == null) {
+                locale = getLocale(null);
+            }
+
+            ResourceBundle rb = getBundle(bundleName, locale);
+            value = getStringOrNull(rb, key);
+
+            if (value == null) {
+                // try to load default
+                value = i18nOriginal.getString(bundleName, locale, key);
+            }
+
+            if (!value.contains("${")) {
+                return value;
+            }
+
+            final RegexBasedInterpolator interpolator = new 
RegexBasedInterpolator();
+            try {
+                interpolator.addValueSource(new EnvarBasedValueSource());
+            } catch (final IOException e) {
+                // In which cases could this happen? And what should we do?
+            }
+
+            interpolator.addValueSource(new 
PropertiesBasedValueSource(System.getProperties()));
+            interpolator.addValueSource(new 
PropertiesBasedValueSource(project.getProperties()));
+            interpolator.addValueSource(new 
PrefixedObjectValueSource("project", project));
+            interpolator.addValueSource(new PrefixedObjectValueSource("pom", 
project));
+            interpolator.addValueSource(new 
PrefixedObjectValueSource("settings", settings));
+
+            try {
+                value = interpolator.interpolate(value);
+            } catch (final InterpolationException e) {
+                // What does this exception mean?
+            }
+
+            return value;
+        }
+
+        /** {@inheritDoc} */
+        public String format(String key, Object arg1) {
+            return format(bundleName, locale, key, new Object[] {arg1});
+        }
+
+        /** {@inheritDoc} */
+        public String format(String key, Object arg1, Object arg2) {
+            return format(bundleName, locale, key, new Object[] {arg1, arg2});
+        }
+
+        /** {@inheritDoc} */
+        public String format(String bundleName, Locale locale, String key, 
Object arg1) {
+            return format(bundleName, locale, key, new Object[] {arg1});
+        }
+
+        /** {@inheritDoc} */
+        public String format(String bundleName, Locale locale, String key, 
Object arg1, Object arg2) {
+            return format(bundleName, locale, key, new Object[] {arg1, arg2});
+        }
+
+        /** {@inheritDoc} */
+        public String format(String bundleName, Locale locale, String key, 
Object[] args) {
+            if (locale == null) {
+                locale = getLocale(null);
+            }
+
+            String value = getString(bundleName, locale, key);
+            if (args == null) {
+                args = NO_ARGS;
+            }
+
+            MessageFormat messageFormat = new MessageFormat("");
+            messageFormat.setLocale(locale);
+            messageFormat.applyPattern(value);
+
+            return messageFormat.format(args);
+        }
+
+        private String getStringOrNull(ResourceBundle rb, String key) {
+            if (rb != null) {
+                try {
+                    return rb.getString(key);
+                } catch (MissingResourceException ignored) {
+                    // intentional
+                }
+            }
+            return null;
+        }
+    }
 }
diff --git 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
index e1a840da0..9e889cd66 100644
--- 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
+++ 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/FailsafeReportMojo.java
@@ -19,15 +19,11 @@
 package org.apache.maven.plugins.surefire.report;
 
 import java.io.File;
-import java.util.Locale;
-import java.util.ResourceBundle;
 
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
 
-import static org.apache.maven.shared.utils.StringUtils.isEmpty;
-
 /**
  * Creates a nicely formatted Failsafe Test Report in html format.
  * This goal does not run the tests, it only builds the reports.
@@ -62,20 +58,6 @@ public class FailsafeReportMojo extends 
AbstractSurefireReportMojo {
     @Parameter(defaultValue = "false", property = "skipFailsafeReport")
     private boolean skipFailsafeReport;
 
-    /**
-     * A custom title of the report for the menu and the project reports page.
-     * @since 2.21.0
-     */
-    @Parameter(defaultValue = "", property = "failsafe.report.title")
-    private String title;
-
-    /**
-     * A custom description for the project reports page.
-     * @since 2.21.0
-     */
-    @Parameter(defaultValue = "", property = "failsafe.report.description")
-    private String description;
-
     @Override
     protected File getSurefireReportsDirectory(MavenProject subProject) {
         String buildDir = subProject.getBuild().getDirectory();
@@ -87,33 +69,6 @@ public class FailsafeReportMojo extends 
AbstractSurefireReportMojo {
         return outputName;
     }
 
-    @Override
-    protected LocalizedProperties getBundle(Locale locale, ClassLoader 
resourceBundleClassLoader) {
-        ResourceBundle bundle = ResourceBundle.getBundle("surefire-report", 
locale, resourceBundleClassLoader);
-        return new LocalizedProperties(bundle) {
-            @Override
-            public String getReportName() {
-                return isEmpty(FailsafeReportMojo.this.getTitle())
-                        ? toLocalizedValue("report.failsafe.name")
-                        : FailsafeReportMojo.this.getTitle();
-            }
-
-            @Override
-            public String getReportDescription() {
-                return isEmpty(FailsafeReportMojo.this.getDescription())
-                        ? toLocalizedValue("report.failsafe.description")
-                        : FailsafeReportMojo.this.getDescription();
-            }
-
-            @Override
-            public String getReportHeader() {
-                return isEmpty(FailsafeReportMojo.this.getTitle())
-                        ? toLocalizedValue("report.failsafe.header")
-                        : FailsafeReportMojo.this.getTitle();
-            }
-        };
-    }
-
     @Override
     protected boolean isSkipped() {
         return skipFailsafeReport;
@@ -125,22 +80,7 @@ public class FailsafeReportMojo extends 
AbstractSurefireReportMojo {
     }
 
     @Override
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-    @Override
-    public String getTitle() {
-        return title;
-    }
-
-    @Override
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
+    protected String getI18Nsection() {
+        return "failsafe";
     }
 }
diff --git 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/LocalizedProperties.java
 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/LocalizedProperties.java
deleted file mode 100644
index 4609c6fb5..000000000
--- 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/LocalizedProperties.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.maven.plugins.surefire.report;
-
-import java.util.ResourceBundle;
-
-/**
- * Surefire Resource Bundle.
- *
- * @author <a href="mailto:tibordig...@apache.org";>Tibor Digana (tibor17)</a>
- */
-public abstract class LocalizedProperties {
-    private final ResourceBundle bundle;
-
-    protected LocalizedProperties(ResourceBundle bundle) {
-        this.bundle = bundle;
-    }
-
-    public abstract String getReportName();
-
-    public abstract String getReportDescription();
-
-    public abstract String getReportHeader();
-
-    protected final String toLocalizedValue(String key) {
-        return bundle.getString(key);
-    }
-
-    public String getReportLabelSummary() {
-        return toLocalizedValue("report.surefire.label.summary");
-    }
-
-    public String getReportLabelTests() {
-        return toLocalizedValue("report.surefire.label.tests");
-    }
-
-    public String getReportLabelErrors() {
-        return toLocalizedValue("report.surefire.label.errors");
-    }
-
-    public String getReportLabelFailures() {
-        return toLocalizedValue("report.surefire.label.failures");
-    }
-
-    public String getReportLabelSkipped() {
-        return toLocalizedValue("report.surefire.label.skipped");
-    }
-
-    public String getReportLabelSuccessRate() {
-        return toLocalizedValue("report.surefire.label.successrate");
-    }
-
-    public String getReportLabelTime() {
-        return toLocalizedValue("report.surefire.label.time");
-    }
-
-    public String getReportLabelPackageList() {
-        return toLocalizedValue("report.surefire.label.packagelist");
-    }
-
-    public String getReportLabelPackage() {
-        return toLocalizedValue("report.surefire.label.package");
-    }
-
-    public String getReportLabelClass() {
-        return toLocalizedValue("report.surefire.label.class");
-    }
-
-    public String getReportLabelTestCases() {
-        return toLocalizedValue("report.surefire.label.testcases");
-    }
-
-    public String getReportLabelFailureDetails() {
-        return toLocalizedValue("report.surefire.label.failuredetails");
-    }
-
-    public String getReportTextNode1() {
-        return toLocalizedValue("report.surefire.text.note1");
-    }
-
-    public String getReportTextNode2() {
-        return toLocalizedValue("report.surefire.text.note2");
-    }
-}
diff --git 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportMojo.java
 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportMojo.java
index 172e30805..92bdae0a5 100644
--- 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportMojo.java
+++ 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportMojo.java
@@ -19,8 +19,6 @@
 package org.apache.maven.plugins.surefire.report;
 
 import java.io.File;
-import java.util.Locale;
-import java.util.ResourceBundle;
 
 import org.apache.maven.plugins.annotations.Execute;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -28,8 +26,6 @@ import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
 
-import static org.apache.maven.shared.utils.StringUtils.isEmpty;
-
 /**
  * Creates a nicely formatted Surefire Test Report in html format.
  *
@@ -61,20 +57,6 @@ public class SurefireReportMojo extends 
AbstractSurefireReportMojo {
     @Parameter(defaultValue = "false", property = "skipSurefireReport")
     private boolean skipSurefireReport;
 
-    /**
-     * A custom title of the report for the menu and the project reports page.
-     * @since 2.21.0
-     */
-    @Parameter(defaultValue = "", property = "surefire.report.title")
-    private String title;
-
-    /**
-     * A custom description for the project reports page.
-     * @since 2.21.0
-     */
-    @Parameter(defaultValue = "", property = "surefire.report.description")
-    private String description;
-
     @Override
     protected File getSurefireReportsDirectory(MavenProject subProject) {
         String buildDir = subProject.getBuild().getDirectory();
@@ -86,33 +68,6 @@ public class SurefireReportMojo extends 
AbstractSurefireReportMojo {
         return outputName;
     }
 
-    @Override
-    protected LocalizedProperties getBundle(Locale locale, ClassLoader 
resourceBundleClassLoader) {
-        ResourceBundle bundle = ResourceBundle.getBundle("surefire-report", 
locale, resourceBundleClassLoader);
-        return new LocalizedProperties(bundle) {
-            @Override
-            public String getReportName() {
-                return isEmpty(SurefireReportMojo.this.getTitle())
-                        ? toLocalizedValue("report.surefire.name")
-                        : SurefireReportMojo.this.getTitle();
-            }
-
-            @Override
-            public String getReportDescription() {
-                return isEmpty(SurefireReportMojo.this.getDescription())
-                        ? toLocalizedValue("report.surefire.description")
-                        : SurefireReportMojo.this.getDescription();
-            }
-
-            @Override
-            public String getReportHeader() {
-                return isEmpty(SurefireReportMojo.this.getTitle())
-                        ? toLocalizedValue("report.surefire.header")
-                        : SurefireReportMojo.this.getTitle();
-            }
-        };
-    }
-
     @Override
     protected boolean isSkipped() {
         return skipSurefireReport;
@@ -124,22 +79,7 @@ public class SurefireReportMojo extends 
AbstractSurefireReportMojo {
     }
 
     @Override
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-    @Override
-    public String getTitle() {
-        return title;
-    }
-
-    @Override
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
+    protected String getI18Nsection() {
+        return "surefire";
     }
 }
diff --git 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportRenderer.java
 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportRenderer.java
index f7684c551..386dcdf8b 100644
--- 
a/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportRenderer.java
+++ 
b/maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportRenderer.java
@@ -31,6 +31,7 @@ import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
 import org.apache.maven.doxia.util.DoxiaUtils;
 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.reporting.AbstractMavenReportRenderer;
+import org.codehaus.plexus.i18n.I18N;
 
 import static org.apache.maven.doxia.markup.HtmlMarkup.A;
 import static org.apache.maven.doxia.sink.SinkEventAttributes.CLASS;
@@ -45,9 +46,9 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
     private static final Object[] TAG_TYPE_START = {HtmlMarkup.TAG_TYPE_START};
     private static final Object[] TAG_TYPE_END = {HtmlMarkup.TAG_TYPE_END};
 
-    // Not used at the moment
+    private final I18N i18n;
+    private final String i18nSection;
     private final Locale locale;
-    private final LocalizedProperties bundle;
 
     private final SurefireReportParser parser;
     private final boolean showSuccess;
@@ -56,15 +57,17 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
 
     public SurefireReportRenderer(
             Sink sink,
+            I18N i18n,
+            String i18nSection,
             Locale locale,
-            LocalizedProperties bundle,
             ConsoleLogger consoleLogger,
             boolean showSuccess,
             List<File> reportsDirectories,
             String xrefLocation) {
         super(sink);
+        this.i18n = i18n;
+        this.i18nSection = i18nSection;
         this.locale = locale;
-        this.bundle = bundle;
         parser = new SurefireReportParser(reportsDirectories, consoleLogger);
         testSuites = parser.parseXMLReportFiles();
         this.showSuccess = showSuccess;
@@ -73,7 +76,28 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
 
     @Override
     public String getTitle() {
-        return bundle.getReportHeader();
+        return getI18nString("title");
+    }
+
+    /**
+     * @param key The key.
+     * @return The translated string.
+     */
+    private String getI18nString(String key) {
+        return getI18nString(getI18Nsection(), key);
+    }
+
+    private String getI18Nsection() {
+        return i18nSection;
+    }
+
+    /**
+     * @param section The section.
+     * @param key The key to translate.
+     * @return the translated key.
+     */
+    private String getI18nString(String section, String key) {
+        return i18n.getString("surefire-report", locale, "report." + section + 
'.' + key);
     }
 
     public void renderBody() {
@@ -103,7 +127,7 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
         sink.section1();
         sinkAnchor("Summary");
         sink.sectionTitle1();
-        sink.text(bundle.getReportLabelSummary());
+        sink.text(getI18nString("surefire", "label.summary"));
         sink.sectionTitle1_();
 
         constructHotLinks();
@@ -113,12 +137,12 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
         startTable();
 
         tableHeader(new String[] {
-            bundle.getReportLabelTests(),
-            bundle.getReportLabelErrors(),
-            bundle.getReportLabelFailures(),
-            bundle.getReportLabelSkipped(),
-            bundle.getReportLabelSuccessRate(),
-            bundle.getReportLabelTime()
+            getI18nString("surefire", "label.tests"),
+            getI18nString("surefire", "label.errors"),
+            getI18nString("surefire", "label.failures"),
+            getI18nString("surefire", "label.skipped"),
+            getI18nString("surefire", "label.successrate"),
+            getI18nString("surefire", "label.time")
         });
 
         tableRow(new String[] {
@@ -134,7 +158,7 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
 
         sink.lineBreak();
 
-        paragraph(bundle.getReportTextNode1());
+        paragraph(getI18nString("surefire", "text.note1"));
 
         sink.lineBreak();
 
@@ -154,7 +178,7 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
         sink.section1();
         sinkAnchor("Package_List");
         sink.sectionTitle1();
-        sink.text(bundle.getReportLabelPackageList());
+        sink.text(getI18nString("surefire", "label.packagelist"));
         sink.sectionTitle1_();
 
         constructHotLinks();
@@ -164,13 +188,13 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
         startTable();
 
         tableHeader(new String[] {
-            bundle.getReportLabelPackage(),
-            bundle.getReportLabelTests(),
-            bundle.getReportLabelErrors(),
-            bundle.getReportLabelFailures(),
-            bundle.getReportLabelSkipped(),
-            bundle.getReportLabelSuccessRate(),
-            bundle.getReportLabelTime()
+            getI18nString("surefire", "label.package"),
+            getI18nString("surefire", "label.tests"),
+            getI18nString("surefire", "label.errors"),
+            getI18nString("surefire", "label.failures"),
+            getI18nString("surefire", "label.skipped"),
+            getI18nString("surefire", "label.successrate"),
+            getI18nString("surefire", "label.time")
         });
 
         for (Map.Entry<String, List<ReportTestSuite>> entry : 
suitePackages.entrySet()) {
@@ -194,7 +218,7 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
         endTable();
         sink.lineBreak();
 
-        paragraph(bundle.getReportTextNode2());
+        paragraph(getI18nString("surefire", "text.note2"));
 
         for (Map.Entry<String, List<ReportTestSuite>> entry : 
suitePackages.entrySet()) {
             String packageName = entry.getKey();
@@ -222,13 +246,13 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
 
                 tableHeader(new String[] {
                     "",
-                    bundle.getReportLabelClass(),
-                    bundle.getReportLabelTests(),
-                    bundle.getReportLabelErrors(),
-                    bundle.getReportLabelFailures(),
-                    bundle.getReportLabelSkipped(),
-                    bundle.getReportLabelSuccessRate(),
-                    bundle.getReportLabelTime()
+                    getI18nString("surefire", "label.class"),
+                    getI18nString("surefire", "label.tests"),
+                    getI18nString("surefire", "label.errors"),
+                    getI18nString("surefire", "label.failures"),
+                    getI18nString("surefire", "label.skipped"),
+                    getI18nString("surefire", "label.successrate"),
+                    getI18nString("surefire", "label.time")
                 });
 
                 for (ReportTestSuite suite : testSuiteList) {
@@ -301,7 +325,7 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
         sink.section1();
         sinkAnchor("Test_Cases");
         sink.sectionTitle1();
-        sink.text(bundle.getReportLabelTestCases());
+        sink.text(getI18nString("surefire", "label.testcases"));
         sink.sectionTitle1_();
 
         constructHotLinks();
@@ -448,7 +472,7 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
         sink.section1();
         sinkAnchor("Failure_Details");
         sink.sectionTitle1();
-        sink.text(bundle.getReportLabelFailureDetails());
+        sink.text(getI18nString("surefire", "label.failuredetails"));
         sink.sectionTitle1_();
 
         constructHotLinks();
@@ -524,15 +548,15 @@ public class SurefireReportRenderer extends 
AbstractMavenReportRenderer {
             sink.paragraph();
 
             sink.text("[");
-            link("#Summary", bundle.getReportLabelSummary());
+            link("#Summary", getI18nString("surefire", "label.summary"));
             sink.text("]");
 
             sink.text(" [");
-            link("#Package_List", bundle.getReportLabelPackageList());
+            link("#Package_List", getI18nString("surefire", 
"label.packagelist"));
             sink.text("]");
 
             sink.text(" [");
-            link("#Test_Cases", bundle.getReportLabelTestCases());
+            link("#Test_Cases", getI18nString("surefire", "label.testcases"));
             sink.text("]");
 
             sink.paragraph_();
diff --git 
a/maven-surefire-report-plugin/src/main/resources/surefire-report.properties 
b/maven-surefire-report-plugin/src/main/resources/surefire-report.properties
index 8aa256e88..8a92b8692 100644
--- a/maven-surefire-report-plugin/src/main/resources/surefire-report.properties
+++ b/maven-surefire-report-plugin/src/main/resources/surefire-report.properties
@@ -17,9 +17,10 @@
 # under the License.
 #
 
-report.surefire.name=Surefire Report
+report.surefire.name=Surefire
 report.surefire.description=Report on the test results of the project.
-report.surefire.header=Surefire Report
+report.surefire.title=Surefire Report
+
 report.surefire.label.summary=Summary
 report.surefire.label.tests=Tests
 report.surefire.label.errors=Errors
@@ -35,6 +36,6 @@ report.surefire.label.failuredetails=Failure Details
 report.surefire.text.note1=Note: failures are anticipated and checked for with 
assertions while errors are unanticipated.
 report.surefire.text.note2=Note: package statistics are not computed 
recursively, they only sum up all of its testsuites numbers.
 
-report.failsafe.name=Failsafe Report
+report.failsafe.name=Failsafe
 report.failsafe.description=Report on the integration test results of the 
project.
 report.failsafe.header=Failsafe Report
diff --git 
a/maven-surefire-report-plugin/src/main/resources/surefire-report_de.properties 
b/maven-surefire-report-plugin/src/main/resources/surefire-report_de.properties
index baff5db5c..2a3bb905e 100644
--- 
a/maven-surefire-report-plugin/src/main/resources/surefire-report_de.properties
+++ 
b/maven-surefire-report-plugin/src/main/resources/surefire-report_de.properties
@@ -17,8 +17,10 @@
 # under the License.
 #
 
+report.surefire.name=Surefire
 report.surefire.description=Bericht \u00FCber die Testresultate des Projekts.
-report.surefire.header=Surefire Bericht
+report.surefire.title=Surefire Bericht
+
 report.surefire.label.class=Klasse
 report.surefire.label.errors=Fehler
 report.surefire.label.failuredetails=Details der Fehlschl\u00E4ge
@@ -31,10 +33,9 @@ report.surefire.label.summary=Zusammenfassung
 report.surefire.label.testcases=Testf\u00E4lle
 report.surefire.label.tests=Tests
 report.surefire.label.time =Zeit
-report.surefire.name=Surefire Bericht
 report.surefire.text.note1 =Hinweis: Fehlschl\u00E4ge werden erwartet und 
durch Behauptungen \u00FCberpr\u00FCft w\u00E4hrend Fehler unerwartet sind.
 report.surefire.text.note2 =Hinweis: Die Paketstatistiken werden nicht 
rekursiv berechnet, es werden lediglich die Ergebnisse aller enthaltenen Tests 
aufsummiert.
 
-report.failsafe.name=Failsafe Bericht
+report.failsafe.name=Failsafe
 report.failsafe.description=Bericht \u00FCber die Integrationstestresultate 
des Projekts.
-report.failsafe.header=Failsafe Bericht
+report.failsafe.title=Failsafe Bericht
diff --git 
a/maven-surefire-report-plugin/src/main/resources/surefire-report_sv.properties 
b/maven-surefire-report-plugin/src/main/resources/surefire-report_sv.properties
index 5e3bcbe65..5d4f734fe 100644
--- 
a/maven-surefire-report-plugin/src/main/resources/surefire-report_sv.properties
+++ 
b/maven-surefire-report-plugin/src/main/resources/surefire-report_sv.properties
@@ -17,9 +17,10 @@
 # under the License.
 #
 
-report.surefire.name=Surefire-rapport
+report.surefire.name=Surefire
 report.surefire.description=Rapport om testresultaten f\u00f6r projektet.
-report.surefire.header=Surefire-rapport
+report.surefire.title=Surefire-rapport
+
 report.surefire.label.summary=\u00d6versikt
 report.surefire.label.tests=Tester
 report.surefire.label.errors=Felaktiga
@@ -35,6 +36,6 @@ report.surefire.label.failuredetails=Detaljer om misslyckade 
tester
 report.surefire.text.note1=Notera: misslyckade tester \u00e4r 
f\u00f6rv\u00e4ntade och har kontrollerats med assertions medan felaktiga 
tester \u00e4r ov\u00e4ntade.
 report.surefire.text.note2=Notera: paketstatistiken ber\u00e4knas inte 
rekursivt, den summerar bara alla testsviters antal.
 
-report.failsafe.name=Failsafe-rapport
+report.failsafe.name=Failsafe
 report.failsafe.description=Rapport om integration testresultaten f\u00f6r 
projektet.
 report.failsafe.header=Failsafe-rapport
diff --git 
a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
 
b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
index d1598a2ee..f1a45fdc2 100644
--- 
a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
+++ 
b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java
@@ -27,6 +27,7 @@ import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.tools.SiteTool;
 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
 import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger;
+import org.codehaus.plexus.i18n.DefaultI18N;
 
 import static java.util.Collections.singletonList;
 import static org.apache.maven.plugins.surefire.report.Utils.toSystemNewLine;
@@ -43,15 +44,11 @@ public class Surefire597Test extends TestCase {
         File report = new File(basedir, "target/test-classes/surefire-597");
         StringWriter writer = new StringWriter();
         Sink sink = new Xhtml5Sink(writer) {};
+        DefaultI18N i18n = new DefaultI18N();
+        i18n.initialize();
         ConsoleLogger consoleLogger = new NullConsoleLogger();
         SurefireReportRenderer r = new SurefireReportRenderer(
-                sink,
-                SiteTool.DEFAULT_LOCALE,
-                new SurefireReportMojo().getBundle(SiteTool.DEFAULT_LOCALE),
-                consoleLogger,
-                true,
-                singletonList(report),
-                null);
+                sink, i18n, "surefire", SiteTool.DEFAULT_LOCALE, 
consoleLogger, true, singletonList(report), null);
         r.render();
         String xml = writer.toString();
         assertThat(
diff --git 
a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java
 
b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java
index 4dfb98a51..1b2634aaf 100644
--- 
a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java
+++ 
b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java
@@ -584,8 +584,6 @@ public class SurefireReportMojoTest extends 
AbstractMojoTestCase {
         File outputDir = (File) getVariableValueFromObject(mojo, 
"outputDirectory");
         String outputName = (String) getVariableValueFromObject(mojo, 
"outputName");
         File reportsDir = (File) getVariableValueFromObject(mojo, 
"reportsDirectory");
-        String title = (String) getVariableValueFromObject(mojo, "title");
-        String description = (String) getVariableValueFromObject(mojo, 
"description");
 
         assertEquals(new File(getBasedir() + 
"/target/site/unit/surefire-1183"), outputDir);
         assertEquals(
@@ -593,8 +591,6 @@ public class SurefireReportMojoTest extends 
AbstractMojoTestCase {
                         .getAbsolutePath(),
                 reportsDir.getAbsolutePath());
         assertEquals("acceptance-test-report", outputName);
-        assertEquals("Acceptance Test", title);
-        assertEquals("Acceptance Test Description", description);
 
         mojo.execute();
 
diff --git 
a/maven-surefire-report-plugin/src/test/resources/unit/surefire-1183/plugin-config.xml
 
b/maven-surefire-report-plugin/src/test/resources/unit/surefire-1183/plugin-config.xml
index 75ad4abd9..108f58350 100644
--- 
a/maven-surefire-report-plugin/src/test/resources/unit/surefire-1183/plugin-config.xml
+++ 
b/maven-surefire-report-plugin/src/test/resources/unit/surefire-1183/plugin-config.xml
@@ -26,10 +26,9 @@
                 <configuration>
                     <project
                             
implementation="org.apache.maven.plugins.surefire.report.stubs.SurefireRepMavenProjectStub"/>
-                    <title>Acceptance Test</title>
-                    <description>Acceptance Test Description</description>
                     <outputName>acceptance-test-report</outputName>
                     <localRepository>${localRepository}</localRepository>
+                    
<customBundle>${basedir}/src/test/resources/unit/surefire-1183/src/site/custom/surefire-report.properties</customBundle>
                     
<outputDirectory>${basedir}/target/site/unit/surefire-1183</outputDirectory>
                     
<reportsDirectory>${basedir}/src/test/resources/unit/surefire-1183/acceptancetest-reports</reportsDirectory>
                 </configuration>
diff --git 
a/maven-surefire-report-plugin/src/test/resources/unit/surefire-1183/src/site/custom/surefire-report.properties
 
b/maven-surefire-report-plugin/src/test/resources/unit/surefire-1183/src/site/custom/surefire-report.properties
new file mode 100644
index 000000000..3e4e9c4b1
--- /dev/null
+++ 
b/maven-surefire-report-plugin/src/test/resources/unit/surefire-1183/src/site/custom/surefire-report.properties
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+report.surefire.name=Acceptance Test
+report.surefire.description=Acceptance Test Description
+report.surefire.title=Acceptance Test
diff --git 
a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1490ReportTitleDescriptionIT.java
 
b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1490ReportTitleDescriptionIT.java
index fdef2c95d..71b85f7f4 100644
--- 
a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1490ReportTitleDescriptionIT.java
+++ 
b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1490ReportTitleDescriptionIT.java
@@ -35,9 +35,9 @@ public class Surefire1490ReportTitleDescriptionIT extends 
SurefireJUnit4Integrat
 
         validator
                 .getSiteFile("project-reports.html")
-                .assertContainsText("Surefire Report")
+                .assertContainsText("Surefire")
                 .assertContainsText("Report on the test results of the 
project.")
-                .assertContainsText("Failsafe Report")
+                .assertContainsText("Failsafe")
                 .assertContainsText("Report on the integration test results of 
the project.");
 
         validator
@@ -53,19 +53,13 @@ public class Surefire1490ReportTitleDescriptionIT extends 
SurefireJUnit4Integrat
 
     @Test
     public void shouldHaveCustomizedReportTitleAndDescription() {
-        OutputValidator validator = unpack().sysProp("failsafe.report.title", 
"failsafe title")
-                .sysProp("failsafe.report.description", "failsafe desc")
-                .sysProp("surefire.report.title", "surefire title")
-                .sysProp("surefire.report.description", "surefire desc")
-                .addGoal("verify")
-                .execute("site")
-                .verifyErrorFreeLog();
+        OutputValidator validator = 
unpack().addGoal("verify").execute("site").verifyErrorFreeLog();
 
         validator
                 .getSiteFile("project-reports.html")
-                .assertContainsText("surefire title")
+                .assertContainsText("surefire name")
                 .assertContainsText("surefire desc")
-                .assertContainsText("failsafe title")
+                .assertContainsText("failsafe name")
                 .assertContainsText("failsafe desc");
 
         validator
diff --git 
a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java
 
b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java
index 5c473af91..139b676ab 100644
--- 
a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java
+++ 
b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java
@@ -25,7 +25,6 @@ import com.gargoylesoftware.htmlunit.WebClient;
 import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
 import com.gargoylesoftware.htmlunit.html.HtmlPage;
 import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
-
 import org.apache.maven.surefire.its.fixture.OutputValidator;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
 import org.apache.maven.surefire.its.fixture.TestFile;
diff --git 
a/surefire-its/src/test/resources/surefire-1490/src/site/custom/surefire-report.properties
 
b/surefire-its/src/test/resources/surefire-1490/src/site/custom/surefire-report.properties
new file mode 100644
index 000000000..3cadaa420
--- /dev/null
+++ 
b/surefire-its/src/test/resources/surefire-1490/src/site/custom/surefire-report.properties
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+report.failsafe.description=failsafe desc
+report.failsafe.name=failsafe name
+report.failsafe.title=failsafe title
+report.surefire.description=surefire desc
+report.surefire.name=surefire name
+report.surefire.title=surefire title


Reply via email to