You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by mi...@apache.org on 2022/11/20 19:09:17 UTC

[maven-doxia-sitetools] 01/01: [DOXIASITETOOLS-271] Overhaul locale support (make Locale#ROOT instead of Locale#ENGLISH default and use full locale)

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

michaelo pushed a commit to branch DOXIASITETOOLS-271
in repository https://gitbox.apache.org/repos/asf/maven-doxia-sitetools.git

commit fbe730ba08f4fba1eb9cc10ddc2c8d7c02541abe
Author: Michael Osipov <mi...@apache.org>
AuthorDate: Sun Nov 6 23:20:06 2022 +0100

    [DOXIASITETOOLS-271] Overhaul locale support (make Locale#ROOT instead of Locale#ENGLISH default and use full locale)
    
    This closes #67
---
 .../apache/maven/doxia/tools/DefaultSiteTool.java  | 264 +++++++++++++++------
 .../org/apache/maven/doxia/tools/SiteTool.java     |  23 +-
 .../org/apache/maven/doxia/tools/SiteToolTest.java |  79 ++++--
 .../unit/site-tool-locales-test/full/pom.xml       |  40 ++++
 .../site-tool-locales-test/full/src/site/site.xml  |  45 ++++
 .../full/src/site/site_de_DE_BY.xml                |  45 ++++
 .../unit/site-tool-locales-test/language/pom.xml   |  40 ++++
 .../language/src/site/site.xml                     |  45 ++++
 .../language/src/site/site_de.xml                  |  45 ++++
 .../language_country/pom.xml                       |  40 ++++
 .../language_country/src/site/site.xml             |  45 ++++
 .../language_country/src/site/site_de_DE.xml       |  45 ++++
 .../doxia/siterenderer/SiteRenderingContext.java   |   2 +-
 .../siterenderer/DefaultSiteRendererTest.java      |   9 +-
 14 files changed, 651 insertions(+), 116 deletions(-)

diff --git a/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/DefaultSiteTool.java b/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/DefaultSiteTool.java
index ca364f5..d061b4d 100644
--- a/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/DefaultSiteTool.java
+++ b/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/DefaultSiteTool.java
@@ -335,14 +335,34 @@ public class DefaultSiteTool
     public File getSiteDescriptor( File siteDirectory, Locale locale )
     {
         Objects.requireNonNull( siteDirectory, "siteDirectory cannot be null" );
-        final Locale llocale = ( locale == null ) ? new Locale( "" ) : locale;
+        Objects.requireNonNull( locale, "locale cannot be null" );
 
-        File siteDescriptor = new File( siteDirectory, "site_" + llocale.getLanguage() + ".xml" );
+        String variant = locale.getVariant();
+        String country = locale.getCountry();
+        String language = locale.getLanguage();
 
-        if ( !siteDescriptor.isFile() )
+        File siteDescriptor = null;
+
+        if ( !variant.isEmpty() )
+        {
+            siteDescriptor = new File( siteDirectory, "site_" + language + "_" + country + "_" + variant + ".xml" );
+        }
+
+        if ( ( siteDescriptor == null || !siteDescriptor.isFile() ) && !country.isEmpty() )
+        {
+            siteDescriptor = new File( siteDirectory, "site_" + language + "_" + country + ".xml" );
+        }
+
+        if ( ( siteDescriptor == null || !siteDescriptor.isFile() ) && !language.isEmpty() )
+        {
+            siteDescriptor = new File( siteDirectory, "site_" + language + ".xml" );
+        }
+
+        if ( siteDescriptor == null || !siteDescriptor.isFile() )
         {
             siteDescriptor = new File( siteDirectory, "site.xml" );
         }
+
         return siteDescriptor;
     }
 
@@ -352,8 +372,8 @@ public class DefaultSiteTool
      * @param project the Maven project, not null.
      * @param localRepository the Maven local repository, not null.
      * @param repositories the Maven remote repositories, not null.
-     * @param locale the locale wanted for the site descriptor. If not null, searching for
-     * <code>site_<i>localeLanguage</i>.xml</code>, otherwise searching for <code>site.xml</code>.
+     * @param locale the locale wanted for the site descriptor, not null.
+     * See {@link #getSiteDescriptor(File, Locale)} for details.
      * @return the site descriptor into the local repository after download of it from repositories or null if not
      * found in repositories.
      * @throws SiteToolException if any
@@ -365,12 +385,11 @@ public class DefaultSiteTool
         Objects.requireNonNull( project, "project cannot be null" );
         Objects.requireNonNull( localRepository, "localRepository cannot be null" );
         Objects.requireNonNull( repositories, "repositories cannot be null" );
-
-        final Locale llocale = ( locale == null ) ? new Locale( "" ) : locale;
+        Objects.requireNonNull( locale, "locale cannot be null" );
 
         try
         {
-            return resolveSiteDescriptor( project, localRepository, repositories, llocale );
+            return resolveSiteDescriptor( project, localRepository, repositories, locale );
         }
         catch ( ArtifactNotFoundException e )
         {
@@ -393,17 +412,17 @@ public class DefaultSiteTool
                                                List<ArtifactRepository> repositories )
         throws SiteToolException
     {
+        Objects.requireNonNull( locale, "locale cannot be null" );
         Objects.requireNonNull( project, "project cannot be null" );
         Objects.requireNonNull( reactorProjects, "reactorProjects cannot be null" );
         Objects.requireNonNull( localRepository, "localRepository cannot be null" );
         Objects.requireNonNull( repositories, "repositories cannot be null" );
 
-        final Locale llocale = ( locale == null ) ? Locale.getDefault() : locale;
-
-        LOGGER.debug( "Computing decoration model of " + project.getId() + " for locale " + llocale );
+        LOGGER.debug( "Computing decoration model of '" + project.getId() + "' for "
+                + ( locale.equals( SiteTool.DEFAULT_LOCALE ) ? "default locale" : "locale '" + locale + "'" ) );
 
         Map.Entry<DecorationModel, MavenProject> result =
-            getDecorationModel( 0, siteDirectory, llocale, project, reactorProjects, localRepository, repositories );
+            getDecorationModel( 0, siteDirectory, locale, project, reactorProjects, localRepository, repositories );
         DecorationModel decorationModel = result.getKey();
         MavenProject parentProject = result.getValue();
 
@@ -423,12 +442,12 @@ public class DefaultSiteTool
 
         if ( parentProject != null )
         {
-            populateParentMenu( decorationModel, llocale, project, parentProject, true );
+            populateParentMenu( decorationModel, locale, project, parentProject, true );
         }
 
         try
         {
-            populateModulesMenu( decorationModel, llocale, project, reactorProjects, localRepository, true );
+            populateModulesMenu( decorationModel, locale, project, reactorProjects, localRepository, true );
         }
         catch ( IOException e )
         {
@@ -506,7 +525,7 @@ public class DefaultSiteTool
      * if used through <code>&lt;menu ref="parent"/&gt;</code>.
      *
      * @param decorationModel the Doxia Sitetools DecorationModel, not null.
-     * @param locale the locale used for the i18n in DecorationModel. If null, using the default locale in the jvm.
+     * @param locale the locale used for the i18n in DecorationModel, not null.
      * @param project a Maven project, not null.
      * @param parentProject a Maven parent project, not null.
      * @param keepInheritedRefs used for inherited references.
@@ -515,6 +534,7 @@ public class DefaultSiteTool
                                     MavenProject parentProject, boolean keepInheritedRefs )
     {
         Objects.requireNonNull( decorationModel, "decorationModel cannot be null" );
+        Objects.requireNonNull( locale, "locale cannot be null" );
         Objects.requireNonNull( project, "project cannot be null" );
         Objects.requireNonNull( parentProject, "parentProject cannot be null" );
 
@@ -530,8 +550,6 @@ public class DefaultSiteTool
             return;
         }
 
-        final Locale llocale = ( locale == null ) ? Locale.getDefault() : locale;
-
         String parentUrl = getDistMgmntSiteUrl( parentProject );
 
         if ( parentUrl != null )
@@ -570,7 +588,7 @@ public class DefaultSiteTool
         {
             if ( menu.getName() == null )
             {
-                menu.setName( i18n.getString( "site-tool", llocale, "decorationModel.menu.parentproject" ) );
+                menu.setName( i18n.getString( "site-tool", locale, "decorationModel.menu.parentproject" ) );
             }
 
             MenuItem item = new MenuItem();
@@ -585,7 +603,7 @@ public class DefaultSiteTool
      * if used through <code>&lt;menu ref="modules"/&gt;</code>.
      *
      * @param decorationModel the Doxia Sitetools DecorationModel, not null.
-     * @param locale the locale used for the i18n in DecorationModel. If null, using the default locale in the jvm.
+     * @param locale the locale used for the i18n in DecorationModel, not null.
      * @param project a Maven project, not null.
      * @param reactorProjects the Maven reactor projects, not null.
      * @param localRepository the Maven local repository, not null.
@@ -598,10 +616,11 @@ public class DefaultSiteTool
                                      boolean keepInheritedRefs )
         throws SiteToolException, IOException
     {
+        Objects.requireNonNull( decorationModel, "decorationModel cannot be null" );
+        Objects.requireNonNull( locale, "locale cannot be null" );
         Objects.requireNonNull( project, "project cannot be null" );
         Objects.requireNonNull( reactorProjects, "reactorProjects cannot be null" );
         Objects.requireNonNull( localRepository, "localRepository cannot be null" );
-        Objects.requireNonNull( decorationModel, "decorationModel cannot be null" );
 
         Menu menu = decorationModel.getMenuRef( "modules" );
 
@@ -615,14 +634,12 @@ public class DefaultSiteTool
             return;
         }
 
-        final Locale llocale = ( locale == null ) ? Locale.getDefault() : locale ;
-
         // we require child modules and reactors to process module menu
         if ( project.getModules().size() > 0 )
         {
             if ( menu.getName() == null )
             {
-                menu.setName( i18n.getString( "site-tool", llocale, "decorationModel.menu.projectmodules" ) );
+                menu.setName( i18n.getString( "site-tool", locale, "decorationModel.menu.projectmodules" ) );
             }
 
             for ( String module : (List<String>) project.getModules() )
@@ -699,6 +716,7 @@ public class DefaultSiteTool
                                      Map<String, List<MavenReport>> categories )
     {
         Objects.requireNonNull( decorationModel, "decorationModel cannot be null" );
+        Objects.requireNonNull( locale, "locale cannot be null" );
         Objects.requireNonNull( categories, "categories cannot be null" );
 
         Menu menu = decorationModel.getMenuRef( "reports" );
@@ -708,11 +726,9 @@ public class DefaultSiteTool
             return;
         }
 
-        final Locale llocale = ( locale == null ) ? Locale.getDefault() : locale;
-
         if ( menu.getName() == null )
         {
-            menu.setName( i18n.getString( "site-tool", llocale, "decorationModel.menu.projectdocumentation" ) );
+            menu.setName( i18n.getString( "site-tool", locale, "decorationModel.menu.projectdocumentation" ) );
         }
 
         boolean found = false;
@@ -722,9 +738,9 @@ public class DefaultSiteTool
             if ( !isEmptyList( categoryReports ) )
             {
                 MenuItem item = createCategoryMenu(
-                                                    i18n.getString( "site-tool", llocale,
+                                                    i18n.getString( "site-tool", locale,
                                                                     "decorationModel.menu.projectinformation" ),
-                                                    "/project-info.html", categoryReports, llocale );
+                                                    "/project-info.html", categoryReports, locale );
                 menu.getItems().add( item );
                 found = true;
             }
@@ -733,8 +749,8 @@ public class DefaultSiteTool
             if ( !isEmptyList( categoryReports ) )
             {
                 MenuItem item =
-                    createCategoryMenu( i18n.getString( "site-tool", llocale, "decorationModel.menu.projectreports" ),
-                                        "/project-reports.html", categoryReports, llocale );
+                    createCategoryMenu( i18n.getString( "site-tool", locale, "decorationModel.menu.projectreports" ),
+                                        "/project-reports.html", categoryReports, locale );
                 menu.getItems().add( item );
                 found = true;
             }
@@ -755,6 +771,7 @@ public class DefaultSiteTool
 
         String[] localesArray = StringUtils.split( locales, "," );
         List<Locale> localesList = new ArrayList<Locale>( localesArray.length );
+        List<Locale> availableLocales = Arrays.asList( Locale.getAvailableLocales() );
 
         for ( String localeString : localesArray )
         {
@@ -765,7 +782,7 @@ public class DefaultSiteTool
                 continue;
             }
 
-            if ( !Arrays.asList( Locale.getAvailableLocales() ).contains( locale ) )
+            if ( !availableLocales.contains( locale ) )
             {
                 if ( LOGGER.isWarnEnabled() )
                 {
@@ -777,18 +794,16 @@ public class DefaultSiteTool
                 continue;
             }
 
-            // Default bundles are in English
-            if ( ( !locale.getLanguage().equals( DEFAULT_LOCALE.getLanguage() ) )
-                && ( !i18n.getBundle( "site-tool", locale ).getLocale().getLanguage()
-                    .equals( locale.getLanguage() ) ) )
+            Locale bundleLocale = i18n.getBundle( "site-tool", locale ).getLocale();
+            if ( !( bundleLocale.equals( locale ) || bundleLocale.getLanguage().equals( locale.getLanguage() ) ) )
             {
                 if ( LOGGER.isWarnEnabled() )
                 {
                     LOGGER.warn( "The locale '" + locale + "' (" + locale.getDisplayName( Locale.ENGLISH )
                         + ") is not currently supported by Maven Site - IGNORING."
-                        + "\nContributions are welcome and greatly appreciated!"
-                        + "\nIf you want to contribute a new translation, please visit "
-                        + "http://maven.apache.org/plugins/localization.html for detailed instructions." );
+                        + System.lineSeparator() + "Contributions are welcome and greatly appreciated!"
+                        + System.lineSeparator() + "If you want to contribute a new translation, please visit "
+                        + "https://maven.apache.org/plugins/localization.html for detailed instructions." );
                 }
 
                 continue;
@@ -808,12 +823,14 @@ public class DefaultSiteTool
     /**
      * Converts a locale code like "en", "en_US" or "en_US_win" to a <code>java.util.Locale</code>
      * object.
-     * <p>If localeCode = <code>default</code>, return the current value of the default locale for this instance
+     * <p>If localeCode = <code>system</code>, return the current value of the default locale for this instance
      * of the Java Virtual Machine.</p>
+     * <p>If localeCode = <code>default</code>, return the root locale.</p>
      *
      * @param localeCode the locale code string.
      * @return a java.util.Locale object instanced or null if errors occurred
-     * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Locale.html">java.util.Locale#getDefault()</a>
+     * @see Locale#getDefault()
+     * @see SiteTool#DEFAULT_LOCALE
      */
     private Locale codeToLocale( String localeCode )
     {
@@ -822,11 +839,16 @@ public class DefaultSiteTool
             return null;
         }
 
-        if ( "default".equalsIgnoreCase( localeCode ) )
+        if ( "system".equalsIgnoreCase( localeCode ) )
         {
             return Locale.getDefault();
         }
 
+        if ( "default".equalsIgnoreCase( localeCode ) )
+        {
+            return SiteTool.DEFAULT_LOCALE;
+        }
+
         String language = "";
         String country = "";
         String variant = "";
@@ -895,47 +917,138 @@ public class DefaultSiteTool
                                         List<ArtifactRepository> repositories, Locale locale )
         throws IOException, ArtifactResolutionException, ArtifactNotFoundException
     {
-        File result;
-
-        // TODO: this is a bit crude - proper type, or proper handling as metadata rather than an artifact in 2.1?
-        Artifact artifact = artifactFactory.createArtifactWithClassifier( project.getGroupId(),
-                                                                          project.getArtifactId(),
-                                                                          project.getVersion(), "xml",
-                                                                          "site_" + locale.getLanguage() );
+        String variant = locale.getVariant();
+        String country = locale.getCountry();
+        String language = locale.getLanguage();
 
+        Artifact artifact = null;
+        File siteDescriptor = null;
         boolean found = false;
-        try
+
+        if ( !variant.isEmpty() )
         {
-            artifactResolver.resolve( artifact, repositories, localRepository );
+            String localeStr = language + "_" + country + "_" + variant;
+            // TODO: this is a bit crude - proper type, or proper handling as metadata rather than an artifact in 2.1?
+            artifact = artifactFactory.createArtifactWithClassifier( project.getGroupId(),
+                                                                     project.getArtifactId(),
+                                                                     project.getVersion(), "xml",
+                                                                     "site_" + localeStr );
+
+            try
+            {
+                artifactResolver.resolve( artifact, repositories, localRepository );
 
-            result = artifact.getFile();
+                siteDescriptor = artifact.getFile();
 
-            // we use zero length files to avoid re-resolution (see below)
-            if ( result.length() > 0 )
+                // we use zero length files to avoid re-resolution (see below)
+                if ( siteDescriptor.length() > 0 )
+                {
+                    found = true;
+                }
+                else
+                {
+                    LOGGER.debug( "No site descriptor found for '" + project.getId() + "' for locale '"
+                        + localeStr + "', trying without variant..." );
+                }
+            }
+            catch ( ArtifactNotFoundException e )
             {
-                found = true;
+                LOGGER.debug( "Unable to locate site descriptor for locale '" + localeStr + "'", e );
+
+                // we can afford to write an empty descriptor here as we don't expect it to turn up later in the
+                // remote repository, because the parent was already released (and snapshots are updated
+                // automatically if changed)
+                siteDescriptor = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
+                siteDescriptor.getParentFile().mkdirs();
+                siteDescriptor.createNewFile();
             }
-            else
+        }
+
+        if ( !found && !country.isEmpty() )
+        {
+            String localeStr = language + "_" + country;
+            // TODO: this is a bit crude - proper type, or proper handling as metadata rather than an artifact in 2.1?
+            artifact = artifactFactory.createArtifactWithClassifier( project.getGroupId(),
+                                                                     project.getArtifactId(),
+                                                                     project.getVersion(), "xml",
+                                                                     "site_" + localeStr );
+
+            try
+            {
+                artifactResolver.resolve( artifact, repositories, localRepository );
+
+                siteDescriptor = artifact.getFile();
+
+                // we use zero length files to avoid re-resolution (see below)
+                if ( siteDescriptor.length() > 0 )
+                {
+                    found = true;
+                }
+                else
+                {
+                    LOGGER.debug( "No site descriptor found for '" + project.getId() + "' for locale '"
+                        + localeStr + "', trying without country..." );
+                }
+            }
+            catch ( ArtifactNotFoundException e )
             {
-                LOGGER.debug( "No site descriptor found for " + project.getId() + " for locale "
-                    + locale.getLanguage() + ", trying without locale..." );
+                LOGGER.debug( "Unable to locate site descriptor for locale '" + localeStr + "'", e );
+
+                // we can afford to write an empty descriptor here as we don't expect it to turn up later in the
+                // remote repository, because the parent was already released (and snapshots are updated
+                // automatically if changed)
+                siteDescriptor = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
+                siteDescriptor.getParentFile().mkdirs();
+                siteDescriptor.createNewFile();
             }
         }
-        catch ( ArtifactNotFoundException e )
+
+
+        if ( !found && !language.isEmpty() )
         {
-            LOGGER.debug( "Unable to locate site descriptor for locale " + locale.getLanguage(), e );
+            String localeStr = language;
+            // TODO: this is a bit crude - proper type, or proper handling as metadata rather than an artifact in 2.1?
+            artifact = artifactFactory.createArtifactWithClassifier( project.getGroupId(),
+                                                                     project.getArtifactId(),
+                                                                     project.getVersion(), "xml",
+                                                                     "site_" + localeStr );
 
-            // we can afford to write an empty descriptor here as we don't expect it to turn up later in the remote
-            // repository, because the parent was already released (and snapshots are updated automatically if changed)
-            result = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
-            result.getParentFile().mkdirs();
-            result.createNewFile();
+            try
+            {
+                artifactResolver.resolve( artifact, repositories, localRepository );
+
+                siteDescriptor = artifact.getFile();
+
+                // we use zero length files to avoid re-resolution (see below)
+                if ( siteDescriptor.length() > 0 )
+                {
+                    found = true;
+                }
+                else
+                {
+                    LOGGER.debug( "No site descriptor found for '" + project.getId() + "' for locale '"
+                        + localeStr + "', trying default locale..." );
+                }
+            }
+            catch ( ArtifactNotFoundException e )
+            {
+                LOGGER.debug( "Unable to locate site descriptor for locale '" + localeStr + "'", e );
+
+                // we can afford to write an empty descriptor here as we don't expect it to turn up later in the
+                // remote repository, because the parent was already released (and snapshots are updated
+                // automatically if changed)
+                siteDescriptor = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
+                siteDescriptor.getParentFile().mkdirs();
+                siteDescriptor.createNewFile();
+            }
         }
 
         if ( !found )
         {
-            artifact = artifactFactory.createArtifactWithClassifier( project.getGroupId(), project.getArtifactId(),
-                                                                     project.getVersion(), "xml", "site" );
+            artifact = artifactFactory.createArtifactWithClassifier( project.getGroupId(),
+                                                                     project.getArtifactId(),
+                                                                     project.getVersion(), "xml",
+                                                                     "site" );
             try
             {
                 artifactResolver.resolve( artifact, repositories, localRepository );
@@ -943,24 +1056,24 @@ public class DefaultSiteTool
             catch ( ArtifactNotFoundException e )
             {
                 // see above regarding this zero length file
-                result = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
-                result.getParentFile().mkdirs();
-                result.createNewFile();
+                siteDescriptor = new File( localRepository.getBasedir(), localRepository.pathOf( artifact ) );
+                siteDescriptor.getParentFile().mkdirs();
+                siteDescriptor.createNewFile();
 
                 throw e;
             }
 
-            result = artifact.getFile();
+            siteDescriptor = artifact.getFile();
 
             // we use zero length files to avoid re-resolution (see below)
-            if ( result.length() == 0 )
+            if ( siteDescriptor.length() == 0 )
             {
-                LOGGER.debug( "No site descriptor found for " + project.getId() + " without locale." );
-                result = null;
+                LOGGER.debug( "No site descriptor found for '" + project.getId() + "' with default locale." );
+                siteDescriptor = null;
             }
         }
 
-        return result;
+        return siteDescriptor;
     }
 
     /**
@@ -1028,7 +1141,7 @@ public class DefaultSiteTool
         }
         catch ( IOException e )
         {
-            throw new SiteToolException( "The site descriptor for " + project.getId() + " cannot be read from "
+            throw new SiteToolException( "The site descriptor for '" + project.getId() + "' cannot be read from "
                 + siteDescriptor, e );
         }
         finally
@@ -1326,6 +1439,7 @@ public class DefaultSiteTool
     {
         if ( distMgmnt != null && distMgmnt.getSite() != null && distMgmnt.getSite().getUrl() != null )
         {
+            // TODO This needs to go, it is just logically wrong
             return urlEncode( distMgmnt.getSite().getUrl() );
         }
 
diff --git a/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/SiteTool.java b/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/SiteTool.java
index b5454ce..a418385 100644
--- a/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/SiteTool.java
+++ b/doxia-integration-tools/src/main/java/org/apache/maven/doxia/tools/SiteTool.java
@@ -39,10 +39,11 @@ import org.apache.maven.reporting.MavenReport;
 public interface SiteTool
 {
     /**
-     * The locale by default for a Maven Site
-     * @see Locale#ENGLISH
+     * The locale by default for a Maven Site.
+     *
+     * @see Locale#ROOT
      */
-    Locale DEFAULT_LOCALE = Locale.ENGLISH;
+    Locale DEFAULT_LOCALE = Locale.ROOT;
 
     /**
      * Get a skin artifact from one of the repositories.
@@ -63,8 +64,9 @@ public interface SiteTool
      * Get a site descriptor from the project's site directory.
      *
      * @param siteDirectory the site directory, not null
-     * @param locale the locale wanted for the site descriptor. If not null, searching for
-     * <code>site_<i>localeLanguage</i>.xml</code>, otherwise searching for <code>site.xml</code>.
+     * @param locale the locale wanted for the site descriptor, not null. Telescoping lookup for
+     * <code>site_language_country_variant.xml</code>, <code>site_language_country.xml</code>,
+     * <code>site_language.xml}</code>, or <code>site.xml</code> as last resort for {@link Locale#ROOT}.
      * @return the site descriptor file
      */ // used by maven-pdf-plugin (should not?)
     File getSiteDescriptor( File siteDirectory, Locale locale );
@@ -107,7 +109,8 @@ public interface SiteTool
      * Get a decoration model for a project.
      *
      * @param siteDirectory the site directory, may be null if project from repository
-     * @param locale the locale used for the i18n in DecorationModel. If null, using the default locale in the jvm.
+     * @param locale the locale used for the i18n in DecorationModel, not null.
+     * See {@link #getSiteDescriptor(File, Locale)} for details.
      * @param project the Maven project, not null.
      * @param reactorProjects the Maven reactor projects, not null.
      * @param localRepository the Maven local repository, not null.
@@ -128,7 +131,8 @@ public interface SiteTool
      * 2 separate menus: "Project Information" and "Project Reports".
      *
      * @param decorationModel the Doxia Sitetools DecorationModel, not null.
-     * @param locale the locale used for the i18n in DecorationModel. If null, using the default locale in the jvm.
+     * @param locale the locale used for the i18n in DecorationModel, not null.
+     * See {@link #getSiteDescriptor(File, Locale)} for details.
      * @param reportsPerCategory reports per category to put in "Reports" or "Information" menus, not null.
      * @see MavenReport#CATEGORY_PROJECT_INFORMATION
      * @see MavenReport#CATEGORY_PROJECT_REPORTS
@@ -138,11 +142,10 @@ public interface SiteTool
 
     /**
      * Extracts from a comma-separated list the locales that are available in <code>site-tool</code>
-     * resource bundle. Notice that <code>default</code> value will be changed to the default locale of
-     * the JVM.
+     * resource bundle.
      *
      * @param locales A comma separated list of locales
-     * @return a list of <code>Locale</code>, which at least contains the Maven default locale which is english
+     * @return a list of <code>Locale</code>s.
      * @since 1.7, was previously getAvailableLocales(String)
      */
     List<Locale> getSiteLocales( String locales );
diff --git a/doxia-integration-tools/src/test/java/org/apache/maven/doxia/tools/SiteToolTest.java b/doxia-integration-tools/src/test/java/org/apache/maven/doxia/tools/SiteToolTest.java
index 071ba27..05b6022 100644
--- a/doxia-integration-tools/src/test/java/org/apache/maven/doxia/tools/SiteToolTest.java
+++ b/doxia-integration-tools/src/test/java/org/apache/maven/doxia/tools/SiteToolTest.java
@@ -212,13 +212,50 @@ public class SiteToolTest
         assertNotNull( tool );
 
         SiteToolMavenProjectStub project = new SiteToolMavenProjectStub( "site-tool-test" );
-        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), null ).toString(),
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), SiteTool.DEFAULT_LOCALE ).toString(),
             project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
         assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.ENGLISH ).toString(),
             project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
         String siteDir = "src/blabla";
-        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), siteDir ), null ).toString(),
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), siteDir ), SiteTool.DEFAULT_LOCALE ).toString(),
             project.getBasedir() + File.separator + "src" + File.separator + "blabla" + File.separator + "site.xml" );
+
+        project = new SiteToolMavenProjectStub( "site-tool-locales-test/full" );
+        final Locale BAVARIAN = new Locale( "de", "DE", "BY" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), SiteTool.DEFAULT_LOCALE ).toString(),
+            project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), BAVARIAN ).toString(),
+            project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site_de_DE_BY.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.GERMANY ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.ENGLISH ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.GERMAN ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+
+        project = new SiteToolMavenProjectStub( "site-tool-locales-test/language_country" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), SiteTool.DEFAULT_LOCALE ).toString(),
+            project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), BAVARIAN ).toString(),
+            project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site_de_DE.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.GERMANY ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site_de_DE.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.ENGLISH ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.GERMAN ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+
+        project = new SiteToolMavenProjectStub( "site-tool-locales-test/language" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), SiteTool.DEFAULT_LOCALE ).toString(),
+            project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), BAVARIAN ).toString(),
+            project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site_de.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.GERMANY ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site_de.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.ENGLISH ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site.xml" );
+        assertEquals( tool.getSiteDescriptor( new File( project.getBasedir(), "src/site" ), Locale.GERMAN ).toString(),
+                project.getBasedir() + File.separator + "src" + File.separator + "site" + File.separator + "site_de.xml" );
     }
 
     /**
@@ -239,7 +276,7 @@ public class SiteToolTest
             + "maven-site-1.0-site.xml";
 
         assertEquals( tool.getSiteDescriptorFromRepository( project, getLocalRepo(),
-                                                            project.getRemoteArtifactRepositories(), Locale.ENGLISH )
+                                                            project.getRemoteArtifactRepositories(), SiteTool.DEFAULT_LOCALE )
             .toString(), result );
     }
 
@@ -257,7 +294,7 @@ public class SiteToolTest
 
         // model from current local build
         DecorationModel model =
-            tool.getDecorationModel( new File( project.getBasedir(), "src/site" ), Locale.getDefault(), project,
+            tool.getDecorationModel( new File( project.getBasedir(), "src/site" ), SiteTool.DEFAULT_LOCALE, project,
                                      reactorProjects, getLocalRepo(), project.getRemoteArtifactRepositories() );
         assertNotNull( model );
         assertNotNull( model.getBannerLeft() );
@@ -269,24 +306,20 @@ public class SiteToolTest
         assertEquals( "http://maven.apache.org/images/maven-small.gif", model.getBannerRight().getSrc() );
         assertNull( model.getBannerRight().getHref() );
 
-        // model from repo: https://repo1.maven.org/maven2/org/apache/maven/maven-site/1.0/maven-site-1.0-site.xml
-        // TODO Enable this test as soon as we haven a site.xml with head content as string
-        /*project.setBasedir( null );
+        // model from repo: https://repo1.maven.org/maven2/org/apache/maven/maven/3.8.6/maven-3.8.6-site.xml
+        project.setBasedir( null );
         project.setGroupId( "org.apache.maven" );
-        project.setArtifactId( "maven-site" );
-        project.setVersion( "1.0" );
+        project.setArtifactId( "maven" );
+        project.setVersion( "3.8.6" );
         DecorationModel modelFromRepo =
-            tool.getDecorationModel( null, Locale.getDefault(), project, reactorProjects, getLocalRepo(),
+            tool.getDecorationModel( null, SiteTool.DEFAULT_LOCALE, project, reactorProjects, getLocalRepo(),
                                      project.getRemoteArtifactRepositories() );
         assertNotNull( modelFromRepo );
         assertNotNull( modelFromRepo.getBannerLeft() );
-        assertEquals( "Maven", modelFromRepo.getBannerLeft().getName() );
-        assertEquals( "images/apache-maven-project-2.png", modelFromRepo.getBannerLeft().getSrc() );
-        assertEquals( "http://maven.apache.org/", modelFromRepo.getBannerLeft().getHref() );
-        assertNotNull( modelFromRepo.getBannerRight() );
-        assertNull( modelFromRepo.getBannerRight().getName() );
-        assertEquals( "images/maven-logo-2.gif", modelFromRepo.getBannerRight().getSrc() );
-        assertNull( modelFromRepo.getBannerRight().getHref() );*/
+        assertEquals( "dummy", modelFromRepo.getBannerLeft().getName() );
+        assertEquals( "https://maven.apache.org/images/apache-maven-project.png", modelFromRepo.getBannerLeft().getSrc() );
+        assertEquals( "https://maven.apache.org/", modelFromRepo.getBannerLeft().getHref() );
+        assertNull( modelFromRepo.getBannerRight() );
     }
 
     /**
@@ -303,7 +336,7 @@ public class SiteToolTest
         List<MavenProject> reactorProjects = new ArrayList<MavenProject>();
 
         DecorationModel model =
-            tool.getDecorationModel( new File( project.getBasedir(), siteDirectory ), Locale.getDefault(), project,
+            tool.getDecorationModel( new File( project.getBasedir(), siteDirectory ), SiteTool.DEFAULT_LOCALE, project,
                                      reactorProjects, getLocalRepo(), project.getRemoteArtifactRepositories() );
         assertNotNull( model );
     }
@@ -312,10 +345,10 @@ public class SiteToolTest
     public void testGetAvailableLocales()
                     throws Exception
     {
-        assertEquals( Collections.singletonList( SiteTool.DEFAULT_LOCALE ), tool.getSiteLocales( "en" ) );
+        assertEquals( Collections.singletonList( SiteTool.DEFAULT_LOCALE ), tool.getSiteLocales( "default" ) );
 
         assertEquals( Arrays.asList( SiteTool.DEFAULT_LOCALE, Locale.FRENCH, Locale.ITALIAN ),
-                      tool.getSiteLocales( "en,fr,it" ) );
+                      tool.getSiteLocales( "default,fr,it" ) );
 
         // by default, only DEFAULT_LOCALE
         assertEquals( Collections.singletonList( SiteTool.DEFAULT_LOCALE ), tool.getSiteLocales( "" ) );
@@ -358,16 +391,16 @@ public class SiteToolTest
         assertNotNull( tool );
 
         SiteToolMavenProjectStub parentProject = new SiteToolMavenProjectStub( "interpolation-parent-test" );
-        parentProject.setDistgributionManagementSiteUrl( "dav:https://davs.codehaus.org/site" );
+        parentProject.setDistgributionManagementSiteUrl( "dav+https://davs.codehaus.org/site" );
 
         SiteToolMavenProjectStub childProject = new SiteToolMavenProjectStub( "interpolation-child-test" );
         childProject.setParent( parentProject );
-        childProject.setDistgributionManagementSiteUrl( "dav:https://davs.codehaus.org/site/child" );
+        childProject.setDistgributionManagementSiteUrl( "dav+https://davs.codehaus.org/site/child" );
 
         List<MavenProject> reactorProjects = Collections.<MavenProject>singletonList( parentProject );
 
         DecorationModel model = tool.getDecorationModel( new File( childProject.getBasedir(), "src/site" ),
-                                                         Locale.getDefault(), childProject, reactorProjects,
+                                                         SiteTool.DEFAULT_LOCALE, childProject, reactorProjects,
                                                          getLocalRepo(), childProject.getRemoteArtifactRepositories() );
         assertNotNull( model );
 
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/pom.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/pom.xml
new file mode 100644
index 0000000..fb40c17
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.shared</groupId>
+  <artifactId>site-tool-test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>dummy</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/src/site/site.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/src/site/site.xml
new file mode 100644
index 0000000..aaa2bae
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/src/site/site.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+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.
+-->
+
+<project name="Maven Dummy Site">
+  <bannerLeft>
+    <name>Maven Site</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-stylus-skin</artifactId>
+  </skin>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/maven2/"/>
+    </links>
+
+    <menu name="Overview">
+      <item name="Test" href="/test.html"/>
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/src/site/site_de_DE_BY.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/src/site/site_de_DE_BY.xml
new file mode 100644
index 0000000..aaa2bae
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/full/src/site/site_de_DE_BY.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+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.
+-->
+
+<project name="Maven Dummy Site">
+  <bannerLeft>
+    <name>Maven Site</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-stylus-skin</artifactId>
+  </skin>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/maven2/"/>
+    </links>
+
+    <menu name="Overview">
+      <item name="Test" href="/test.html"/>
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/pom.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/pom.xml
new file mode 100644
index 0000000..fb40c17
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.shared</groupId>
+  <artifactId>site-tool-test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>dummy</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/src/site/site.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/src/site/site.xml
new file mode 100644
index 0000000..aaa2bae
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/src/site/site.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+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.
+-->
+
+<project name="Maven Dummy Site">
+  <bannerLeft>
+    <name>Maven Site</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-stylus-skin</artifactId>
+  </skin>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/maven2/"/>
+    </links>
+
+    <menu name="Overview">
+      <item name="Test" href="/test.html"/>
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/src/site/site_de.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/src/site/site_de.xml
new file mode 100644
index 0000000..aaa2bae
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language/src/site/site_de.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+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.
+-->
+
+<project name="Maven Dummy Site">
+  <bannerLeft>
+    <name>Maven Site</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-stylus-skin</artifactId>
+  </skin>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/maven2/"/>
+    </links>
+
+    <menu name="Overview">
+      <item name="Test" href="/test.html"/>
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/pom.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/pom.xml
new file mode 100644
index 0000000..fb40c17
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.shared</groupId>
+  <artifactId>site-tool-test</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>dummy</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/src/site/site.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/src/site/site.xml
new file mode 100644
index 0000000..aaa2bae
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/src/site/site.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+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.
+-->
+
+<project name="Maven Dummy Site">
+  <bannerLeft>
+    <name>Maven Site</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-stylus-skin</artifactId>
+  </skin>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/maven2/"/>
+    </links>
+
+    <menu name="Overview">
+      <item name="Test" href="/test.html"/>
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>
diff --git a/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/src/site/site_de_DE.xml b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/src/site/site_de_DE.xml
new file mode 100644
index 0000000..aaa2bae
--- /dev/null
+++ b/doxia-integration-tools/src/test/resources/unit/site-tool-locales-test/language_country/src/site/site_de_DE.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+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.
+-->
+
+<project name="Maven Dummy Site">
+  <bannerLeft>
+    <name>Maven Site</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-stylus-skin</artifactId>
+  </skin>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/maven2/"/>
+    </links>
+
+    <menu name="Overview">
+      <item name="Test" href="/test.html"/>
+    </menu>
+    <menu ref="reports"/>
+  </body>
+</project>
diff --git a/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java b/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java
index 434f971..1b4c57b 100644
--- a/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java
+++ b/doxia-site-renderer/src/main/java/org/apache/maven/doxia/siterenderer/SiteRenderingContext.java
@@ -50,7 +50,7 @@ public class SiteRenderingContext
 
     private Map<String, ?> templateProperties;
 
-    private Locale locale = Locale.getDefault();
+    private Locale locale = Locale.ROOT;
 
     private List<Locale> siteLocales = new ArrayList<Locale>();
 
diff --git a/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java b/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java
index e3eb8b4..2ccc2b5 100644
--- a/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java
+++ b/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java
@@ -140,9 +140,6 @@ public class DefaultSiteRendererTest
             IOUtil.close( skinIS );
             IOUtil.close( jarOS );
         }
-
-        oldLocale = Locale.getDefault();
-        Locale.setDefault( Locale.ENGLISH );
     }
 
     /**
@@ -153,8 +150,6 @@ public class DefaultSiteRendererTest
         throws Exception
     {
         container.release( renderer );
-
-        Locale.setDefault( oldLocale );
     }
 
     /**
@@ -345,7 +340,7 @@ public class DefaultSiteRendererTest
         skin.setFile( skinFile );
         SiteRenderingContext siteRenderingContext =
             renderer.createContextForSkin( skin, attributes, new DecorationModel(), "defaultWindowTitle",
-                                           Locale.ENGLISH );
+                                           Locale.ROOT );
         RenderingContext context = new RenderingContext( new File( "" ), "document.html", "generator" );
         SiteRendererSink sink = new SiteRendererSink( context );
         renderer.mergeDocumentIntoSite( writer, sink, siteRenderingContext );
@@ -379,7 +374,7 @@ public class DefaultSiteRendererTest
         skin.setFile( skinFile );
         SiteRenderingContext siteRenderingContext =
             renderer.createContextForSkin( skin, attributes,decoration, "defaultWindowTitle",
-                                                   Locale.ENGLISH );
+                                                   Locale.ROOT );
         siteRenderingContext.addSiteDirectory( getTestFile( siteDir ) );
         siteRenderingContext.setValidate( validate );