diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2011-07-29 12:09:43 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2011-07-29 12:09:43 +0200 |
commit | 402f8958a403d94422f38d47cc39aba0f13e8aae (patch) | |
tree | e4bac52b9a2927d7e994d9961bacf6d880611db7 /sonar-core | |
parent | 15f5d562a3da55f3702500c1c855f3f9d7a52e2d (diff) | |
download | sonarqube-402f8958a403d94422f38d47cc39aba0f13e8aae.tar.gz sonarqube-402f8958a403d94422f38d47cc39aba0f13e8aae.zip |
SONAR-75 Improve i18n API
- The extension point LanguagePack is not required anymore
- No error logs when rule description is not available in all locales
- Increase code coverage and decrease complexity
Diffstat (limited to 'sonar-core')
12 files changed, 460 insertions, 32 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/i18n/I18nManager.java b/sonar-core/src/main/java/org/sonar/core/i18n/I18nManager.java index a99ba3397bf..45f31b36853 100644 --- a/sonar-core/src/main/java/org/sonar/core/i18n/I18nManager.java +++ b/sonar-core/src/main/java/org/sonar/core/i18n/I18nManager.java @@ -20,50 +20,145 @@ package org.sonar.core.i18n; import com.google.common.collect.Maps; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.ServerExtension; import org.sonar.api.i18n.I18n; import org.sonar.api.platform.PluginMetadata; import org.sonar.api.platform.PluginRepository; +import org.sonar.api.utils.SonarException; +import java.io.IOException; +import java.io.InputStream; import java.text.MessageFormat; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; +import java.util.*; public class I18nManager implements I18n, ServerExtension { + private static Logger LOG = LoggerFactory.getLogger(I18nManager.class); + + public static final String ENGLISH_PACK_PLUGIN_KEY = "i18nen"; + public static final String BUNDLE_PACKAGE = "org.sonar.i18n."; private PluginRepository pluginRepository; - private Map<String, ClassLoader> bundleToClassloader; + private Map<String, ClassLoader> bundleToClassloaders; + private Map<String, String> propertyToBundles; public I18nManager(PluginRepository pluginRepository) { this.pluginRepository = pluginRepository; } - I18nManager(Map<String, ClassLoader> bundleToClassloader) { - this.bundleToClassloader = bundleToClassloader; + I18nManager(Map<String, ClassLoader> bundleToClassloaders) { + this.bundleToClassloaders = bundleToClassloaders; } public void start() { - ClassLoader coreClassLoader = pluginRepository.getPlugin("i18nen").getClass().getClassLoader(); + initClassloaders(); + initProperties(); + } + + private void initClassloaders() { + if (bundleToClassloaders == null) { + ClassLoader coreClassLoader = pluginRepository.getPlugin(ENGLISH_PACK_PLUGIN_KEY).getClass().getClassLoader(); + bundleToClassloaders = Maps.newHashMap(); + for (PluginMetadata metadata : pluginRepository.getMetadata()) { + if (!metadata.isCore() && !ENGLISH_PACK_PLUGIN_KEY.equals(metadata.getBasePlugin())) { + // plugin but not a language pack + // => plugins embedd only their own bundles with all locales + ClassLoader classLoader = pluginRepository.getPlugin(metadata.getKey()).getClass().getClassLoader(); + bundleToClassloaders.put(BUNDLE_PACKAGE + metadata.getKey(), classLoader); - bundleToClassloader = Maps.newHashMap(); - for (PluginMetadata metadata : pluginRepository.getMetadata()) { - if (!metadata.isCore() && !"i18nen".equals(metadata.getBasePlugin())) { - ClassLoader classLoader = pluginRepository.getPlugin(metadata.getKey()).getClass().getClassLoader(); - bundleToClassloader.put(metadata.getKey(), classLoader); + } else if (metadata.isCore()) { + // bundles of core plugins are defined into language packs. All language packs are supposed + // to share the same classloader (english pack classloader) + bundleToClassloaders.put(BUNDLE_PACKAGE + metadata.getKey(), coreClassLoader); + } + } + } + bundleToClassloaders = Collections.unmodifiableMap(bundleToClassloaders); + } - } else if (metadata.isCore()) { - bundleToClassloader.put(metadata.getKey(), coreClassLoader); + private void initProperties() { + propertyToBundles = Maps.newHashMap(); + for (Map.Entry<String, ClassLoader> entry : bundleToClassloaders.entrySet()) { + try { + String bundleKey = entry.getKey(); + ResourceBundle bundle = ResourceBundle.getBundle(bundleKey, Locale.ENGLISH, entry.getValue()); + Enumeration<String> keys = bundle.getKeys(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + propertyToBundles.put(key, bundleKey); + } + } catch (MissingResourceException e) { + // ignore } } + propertyToBundles = Collections.unmodifiableMap(propertyToBundles); + LOG.debug(String.format("Loaded %d properties from English bundles", propertyToBundles.size())); } public String message(Locale locale, String key, String defaultValue, Object... parameters) { - String bundle = keyToBundle(key); - ResourceBundle resourceBundle = ResourceBundle.getBundle(bundle, locale, bundleToClassloader.get(bundle)); - String value = resourceBundle.getString(key); - if (value==null) { + String bundleKey = propertyToBundles.get(key); + ResourceBundle resourceBundle = getBundle(bundleKey, locale); + return message(resourceBundle, key, defaultValue, parameters); + } + + /** + * Results are not kept in cache. + */ + String messageFromFile(Locale locale, String filename, String relatedProperty) { + ClassLoader classloader = getClassLoaderForProperty(relatedProperty); + String result = null; + if (classloader != null) { + String bundleBase = propertyToBundles.get(relatedProperty); + String filePath = bundleBase.replace('.', '/'); + if (locale != Locale.ENGLISH) { + filePath += "_" + locale.toString(); + } + filePath += "/" + filename; + InputStream input = classloader.getResourceAsStream(filePath); + if (input != null) { + try { + result = IOUtils.toString(input, "UTF-8"); + } catch (IOException e) { + throw new SonarException("Fail to load file: " + filePath, e); + } finally { + IOUtils.closeQuietly(input); + } + } + } + return result; + } + + ResourceBundle getBundle(String bundleKey, Locale locale) { + try { + ClassLoader classloader = bundleToClassloaders.get(bundleKey); + if (classloader != null) { + return ResourceBundle.getBundle(bundleKey, locale, classloader); + } + } catch (MissingResourceException e) { + // ignore + } + return null; + } + + + ClassLoader getClassLoaderForProperty(String propertyKey) { + String bundleKey = propertyToBundles.get(propertyKey); + return (bundleKey != null ? bundleToClassloaders.get(bundleKey) : null); + } + + String message(ResourceBundle resourceBundle, String key, String defaultValue, Object... parameters) { + String value = null; + if (resourceBundle != null) { + try { + value = resourceBundle.getString(key); + } catch (MissingResourceException e) { + // ignore + } + } + if (value == null) { value = defaultValue; } if (value != null && parameters.length > 0) { @@ -72,11 +167,11 @@ public class I18nManager implements I18n, ServerExtension { return value; } - String keyToBundle(String key) { - String pluginKey = StringUtils.substringBefore(key, "."); - if (bundleToClassloader.containsKey(pluginKey)) { - return pluginKey; + String extractBundleFromKey(String key) { + String bundleKey = BUNDLE_PACKAGE + StringUtils.substringBefore(key, "."); + if (bundleToClassloaders.containsKey(bundleKey)) { + return bundleKey; } - return "core"; + return BUNDLE_PACKAGE + "core"; } } diff --git a/sonar-core/src/main/java/org/sonar/core/i18n/RuleI18nManager.java b/sonar-core/src/main/java/org/sonar/core/i18n/RuleI18nManager.java new file mode 100644 index 00000000000..764871806cc --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/i18n/RuleI18nManager.java @@ -0,0 +1,111 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.core.i18n; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.ServerComponent; + +import java.util.Locale; + +public class RuleI18nManager implements ServerComponent { + + private I18nManager i18nManager; + + public RuleI18nManager(I18nManager i18nManager) { + this.i18nManager = i18nManager; + } + + public String getName(String repositoryKey, String ruleKey, Locale locale) { + return message(repositoryKey, ruleKey, locale, ".name", ruleKey); + } + + public String getDescription(String repositoryKey, String ruleKey, Locale locale) { + String relatedProperty = "rule." + repositoryKey + "." + ruleKey + ".name"; + + // TODO add cache + String description = i18nManager.messageFromFile(locale, ruleKey + ".html", relatedProperty); + if (description == null && !Locale.ENGLISH.equals(locale)) { + description = i18nManager.messageFromFile(Locale.ENGLISH, ruleKey + ".html", relatedProperty); + } + return StringUtils.defaultString(description, ""); + } + + public String getParamDescription(String repositoryKey, String ruleKey, String paramKey, Locale locale) { + return message(repositoryKey, ruleKey, locale, ".param." + paramKey, ""); + } + + private String message(String repositoryKey, String ruleKey, Locale locale, String suffix, String defaultValue) { + String propertyKey = new StringBuilder().append("rule.").append(repositoryKey).append(".").append(ruleKey).append(suffix).toString(); + return i18nManager.message(locale, propertyKey, defaultValue); + } + +// static class RuleKey { +// private String repositoryKey; +// private String key; +// +// RuleKey(String repositoryKey, String key) { +// this.repositoryKey = repositoryKey; +// this.key = key; +// } +// +// public String getRepositoryKey() { +// return repositoryKey; +// } +// +// public String getKey() { +// return key; +// } +// +// @Override +// public boolean equals(Object o) { +// if (this == o) return true; +// if (o == null || getClass() != o.getClass()) return false; +// +// RuleKey ruleKey = (RuleKey) o; +// +// if (!key.equals(ruleKey.key)) return false; +// if (!repositoryKey.equals(ruleKey.repositoryKey)) return false; +// +// return true; +// } +// +// @Override +// public int hashCode() { +// int result = repositoryKey.hashCode(); +// result = 31 * result + key.hashCode(); +// return result; +// } +// +// @Override +// public String toString() { +// return new StringBuilder().append(repositoryKey).append(":").append(key).toString(); +// } +// } +// +// static class RuleMessages { +// private String name; +// private String description; +// +// RuleMessages(String name, String description) { +// this.name = name; +// this.description = description; +// } +// } +} diff --git a/sonar-core/src/test/java/org/sonar/core/i18n/I18nManagerTest.java b/sonar-core/src/test/java/org/sonar/core/i18n/I18nManagerTest.java index af57b768738..b2ef460c993 100644 --- a/sonar-core/src/test/java/org/sonar/core/i18n/I18nManagerTest.java +++ b/sonar-core/src/test/java/org/sonar/core/i18n/I18nManagerTest.java @@ -20,25 +20,145 @@ package org.sonar.core.i18n; import com.google.common.collect.Maps; +import org.hamcrest.CoreMatchers; import org.hamcrest.core.Is; +import org.junit.Before; import org.junit.Test; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Locale; import java.util.Map; +import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; +import static org.sonar.core.i18n.I18nManager.BUNDLE_PACKAGE; public class I18nManagerTest { + private I18nManager manager; + private ClassLoader coreClassLoader; + private ClassLoader sqaleClassLoader; + + @Before + public void init() { + coreClassLoader = newCoreClassLoader(); + sqaleClassLoader = newSqaleClassLoader(); + Map<String, ClassLoader> bundleToClassLoaders = Maps.newHashMap(); + bundleToClassLoaders.put(BUNDLE_PACKAGE + "core", coreClassLoader); + bundleToClassLoaders.put(BUNDLE_PACKAGE + "checkstyle", coreClassLoader); + bundleToClassLoaders.put(BUNDLE_PACKAGE + "sqale", sqaleClassLoader); + manager = new I18nManager(bundleToClassLoaders); + manager.start(); + } + @Test - public void shouldExtractBundleKey() { - Map<String,ClassLoader> bundleToClassLoaders = Maps.newHashMap(); - bundleToClassLoaders.put("core", getClass().getClassLoader()); - bundleToClassLoaders.put("checkstyle", getClass().getClassLoader()); - bundleToClassLoaders.put("sqale", getClass().getClassLoader()); + public void shouldExtractPluginFromKey() { + Map<String, ClassLoader> bundleToClassLoaders = Maps.newHashMap(); + bundleToClassLoaders.put(BUNDLE_PACKAGE + "core", getClass().getClassLoader()); + bundleToClassLoaders.put(BUNDLE_PACKAGE + "checkstyle", getClass().getClassLoader()); + bundleToClassLoaders.put(BUNDLE_PACKAGE + "sqale", getClass().getClassLoader()); I18nManager i18n = new I18nManager(bundleToClassLoaders); + i18n.start(); + + assertThat(i18n.extractBundleFromKey("by"), Is.is(BUNDLE_PACKAGE + "core")); + assertThat(i18n.extractBundleFromKey("violations_drilldown.page"), Is.is(BUNDLE_PACKAGE + "core")); + assertThat(i18n.extractBundleFromKey("checkstyle.rule1.name"), Is.is(BUNDLE_PACKAGE + "checkstyle")); + assertThat(i18n.extractBundleFromKey("sqale.console.page"), Is.is(BUNDLE_PACKAGE + "sqale")); + } + + @Test + public void shouldFindKeysInEnglishLanguagePack() { + assertThat(manager.message(Locale.ENGLISH, "checkstyle.rule1.name", null), Is.is("Rule one")); + assertThat(manager.message(Locale.ENGLISH, "by", null), Is.is("By")); + assertThat(manager.message(Locale.ENGLISH, "sqale.page", null), Is.is("Sqale page title")); + + assertThat(manager.message(Locale.FRENCH, "checkstyle.rule1.name", null), Is.is("Rule un")); + assertThat(manager.message(Locale.FRENCH, "by", null), Is.is("Par")); + assertThat(manager.message(Locale.FRENCH, "sqale.page", null), Is.is("Titre de la page Sqale")); + } + + @Test + public void shouldUseDefaultLocale() { + assertThat(manager.message(Locale.CHINA, "checkstyle.rule1.name", null), Is.is("Rule one")); + assertThat(manager.message(Locale.CHINA, "by", null), Is.is("By")); + assertThat(manager.message(Locale.CHINA, "sqale.page", null), Is.is("Sqale page title")); + } + + @Test + public void shouldUseLanguagePack() { + assertThat(manager.message(Locale.FRENCH, "checkstyle.rule1.name", null), Is.is("Rule un")); + assertThat(manager.message(Locale.FRENCH, "by", null), Is.is("Par")); + assertThat(manager.message(Locale.FRENCH, "sqale.page", null), Is.is("Titre de la page Sqale")); + } + + @Test + public void shouldReturnDefaultValueIfMissingKey() { + assertThat(manager.message(Locale.ENGLISH, "foo.unknown", "default"), Is.is("default")); + assertThat(manager.message(Locale.FRENCH, "foo.unknown", "default"), Is.is("default")); + } + + @Test + public void shouldAcceptEmptyLabels() { + assertThat(manager.message(Locale.ENGLISH, "empty", "default"), Is.is("")); + assertThat(manager.message(Locale.FRENCH, "empty", "default"), Is.is("")); + } + + @Test + public void shouldFormatMessageWithParameters() { + assertThat(manager.message(Locale.ENGLISH, "with.parameters", null, "one", "two"), Is.is("First is one and second is two")); + } + + @Test + public void shouldUseDefaultLocaleIfMissingValueInLocalizedBundle() { + assertThat(manager.message(Locale.FRENCH, "only.in.english", null), Is.is("Missing in French bundle")); + assertThat(manager.message(Locale.CHINA, "only.in.english", null), Is.is("Missing in French bundle")); + } + + @Test + public void shouldGetClassLoaderByProperty() { + assertThat(manager.getClassLoaderForProperty("foo.unknown"), nullValue()); + assertThat(manager.getClassLoaderForProperty("by"), Is.is(coreClassLoader)); + assertThat(manager.getClassLoaderForProperty("sqale.page"), Is.is(sqaleClassLoader)); + } + + @Test + public void shouldFindEnglishFile() { + String html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name" /* any property in the same bundle */); + assertThat(html, Is.is("This is the architecture rule")); + } + + @Test + public void shouldNotFindFile() { + String html = manager.messageFromFile(Locale.ENGLISH, "UnknownRule.html", "checkstyle.rule1.name" /* any property in the same bundle */); + assertThat(html, nullValue()); + } + + @Test + public void shouldFindFrenchFile() { + String html = manager.messageFromFile(Locale.FRENCH, "ArchitectureRule.html", "checkstyle.rule1.name" /* any property in the same bundle */); + assertThat(html, Is.is("Règle d'architecture")); + } + + @Test + public void shouldNotFindMissingLocale() { + String html = manager.messageFromFile(Locale.CHINA, "ArchitectureRule.html", "checkstyle.rule1.name" /* any property in the same bundle */); + assertThat(html, nullValue()); + } + + + private URLClassLoader newSqaleClassLoader() { + return newClassLoader("/org/sonar/core/i18n/sqalePlugin/"); + } + + private URLClassLoader newCoreClassLoader() { + return newClassLoader("/org/sonar/core/i18n/englishPack/", "/org/sonar/core/i18n/frenchPack/"); + } - assertThat(i18n.keyToBundle("by"), Is.is("core")); - assertThat(i18n.keyToBundle("violations_drilldown.page"), Is.is("core")); - assertThat(i18n.keyToBundle("checkstyle.rule1.name"), Is.is("checkstyle")); - assertThat(i18n.keyToBundle("sqale.console.page"), Is.is("sqale")); + private URLClassLoader newClassLoader(String... resourcePaths) { + URL[] urls = new URL[resourcePaths.length]; + for (int index = 0; index < resourcePaths.length; index++) { + urls[index] = getClass().getResource(resourcePaths[index]); + } + return new URLClassLoader(urls); } } diff --git a/sonar-core/src/test/java/org/sonar/core/i18n/RuleI18nManagerTest.java b/sonar-core/src/test/java/org/sonar/core/i18n/RuleI18nManagerTest.java new file mode 100644 index 00000000000..17608330075 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/i18n/RuleI18nManagerTest.java @@ -0,0 +1,90 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.core.i18n; + +import org.hamcrest.core.Is; +import org.junit.Test; + +import java.util.Locale; + +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.isNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +public class RuleI18nManagerTest { + @Test + public void shouldGetName() { + I18nManager i18n = mock(I18nManager.class); + RuleI18nManager ruleI18n = new RuleI18nManager(i18n); + + ruleI18n.getName("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.ENGLISH); + + String propertyKey = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.name"; + verify(i18n).message(Locale.ENGLISH, propertyKey, "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck" /* default value is the key */); + verifyNoMoreInteractions(i18n); + } + + @Test + public void shouldGetParamDescription() { + I18nManager i18n = mock(I18nManager.class); + RuleI18nManager ruleI18n = new RuleI18nManager(i18n); + + ruleI18n.getParamDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", "pattern", Locale.ENGLISH); + + String propertyKey = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.param.pattern"; + verify(i18n).message(Locale.ENGLISH, propertyKey, "" /* default value must be blank */); + verifyNoMoreInteractions(i18n); + } + + @Test + public void shouldGetDescriptionFromFile() { + I18nManager i18n = mock(I18nManager.class); + RuleI18nManager ruleI18n = new RuleI18nManager(i18n); + + ruleI18n.getDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.ENGLISH); + + String propertyKeyForName = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.name"; + verify(i18n).messageFromFile(Locale.ENGLISH, "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName); + verifyNoMoreInteractions(i18n); + } + + @Test + public void shoudlReturnBlankIfMissingDescription() { + I18nManager i18n = mock(I18nManager.class); + RuleI18nManager ruleI18n = new RuleI18nManager(i18n); + + assertThat(ruleI18n.getDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.ENGLISH), Is.is("")); + } + + @Test + public void shouldUseEnglishIfMissingLocale() { + I18nManager i18n = mock(I18nManager.class); + RuleI18nManager ruleI18n = new RuleI18nManager(i18n); + + ruleI18n.getDescription("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck", Locale.FRENCH); + + String propertyKeyForName = "rule.checkstyle.com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.name"; + verify(i18n).messageFromFile(Locale.FRENCH, "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName); + verify(i18n).messageFromFile(Locale.ENGLISH, "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.html", propertyKeyForName); + verifyNoMoreInteractions(i18n); + } +} diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/checkstyle.properties b/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/checkstyle.properties new file mode 100644 index 00000000000..10fa9295c44 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/checkstyle.properties @@ -0,0 +1 @@ +checkstyle.rule1.name=Rule one diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/checkstyle/ArchitectureRule.html b/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/checkstyle/ArchitectureRule.html new file mode 100644 index 00000000000..a7cad9049d7 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/checkstyle/ArchitectureRule.html @@ -0,0 +1 @@ +This is the architecture rule
\ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/core.properties b/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/core.properties new file mode 100644 index 00000000000..de205d651cb --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/englishPack/org/sonar/i18n/core.properties @@ -0,0 +1,4 @@ +by=By +empty= +with.parameters=First is {0} and second is {1} +only.in.english=Missing in French bundle
\ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/checkstyle_fr.properties b/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/checkstyle_fr.properties new file mode 100644 index 00000000000..b2fc8f9651f --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/checkstyle_fr.properties @@ -0,0 +1 @@ +checkstyle.rule1.name=Rule un
\ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/checkstyle_fr/ArchitectureRule.html b/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/checkstyle_fr/ArchitectureRule.html new file mode 100644 index 00000000000..9b12ae071ce --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/checkstyle_fr/ArchitectureRule.html @@ -0,0 +1 @@ +Règle d'architecture
\ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/core_fr.properties b/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/core_fr.properties new file mode 100644 index 00000000000..e9ced4039ae --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/frenchPack/org/sonar/i18n/core_fr.properties @@ -0,0 +1,2 @@ +by=Par +empty=
\ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/sqalePlugin/org/sonar/i18n/sqale.properties b/sonar-core/src/test/resources/org/sonar/core/i18n/sqalePlugin/org/sonar/i18n/sqale.properties new file mode 100644 index 00000000000..a8ea9c0553e --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/sqalePlugin/org/sonar/i18n/sqale.properties @@ -0,0 +1 @@ +sqale.page=Sqale page title
\ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/i18n/sqalePlugin/org/sonar/i18n/sqale_fr.properties b/sonar-core/src/test/resources/org/sonar/core/i18n/sqalePlugin/org/sonar/i18n/sqale_fr.properties new file mode 100644 index 00000000000..471d015a11a --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/i18n/sqalePlugin/org/sonar/i18n/sqale_fr.properties @@ -0,0 +1 @@ +sqale.page=Titre de la page Sqale
\ No newline at end of file |