Skip to content

Commit

Permalink
Use PropertyResourceBundle for localization (#357)
Browse files Browse the repository at this point in the history
Co-authored-by: Basil Crow <me@basilcrow.com>
Co-authored-by: Jesse Glick <jglick@cloudbees.com>
  • Loading branch information
3 people committed May 9, 2022
1 parent 2c1c07b commit 3b5035c
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 20 deletions.
42 changes: 22 additions & 20 deletions jelly/src/main/java/org/kohsuke/stapler/jelly/ResourceBundle.java
Expand Up @@ -24,6 +24,12 @@
package org.kohsuke.stapler.jelly;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.FileNotFoundException;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.PropertyResourceBundle;
import org.kohsuke.stapler.MetaClass;
import org.kohsuke.stapler.WebApp;

Expand All @@ -39,7 +45,7 @@

/**
* Cache of localization strings.
*
*
* @author Kohsuke Kawaguchi
*/
public class ResourceBundle {
Expand Down Expand Up @@ -142,29 +148,25 @@ protected Properties get(String key) {
// attempt to load
props = new Properties();
String url = baseName + key + ".properties";
InputStream in=null;
try {
in = openStream(url);
// an user reported that on IBM JDK, URL.openStream
// returns null instead of IOException.
// see http://www.nabble.com/WAS---Hudson-tt16026561.html
} catch (IOException e) {
// failed.
}
try (InputStream in = openStream(url)) {
PropertyResourceBundle propertyResourceBundle = new PropertyResourceBundle(in);

if(in!=null) {
try {
try {
props.load(in);
} finally {
in.close();
}
} catch (IOException e) {
throw new Error("Failed to load "+url,e);
Enumeration<String> keys = propertyResourceBundle.getKeys();
// TODO Java 9+ can use 'asIterator' and get rid of below collections conversion
List<String> keysAsSaneType = Collections.list(keys);

for (String localKey : keysAsSaneType) {
String value = propertyResourceBundle.getString(localKey);
props.setProperty(localKey, value);
}

} catch (FileNotFoundException ignored) {
// we fall back to the default properties file if a locale file is missing
} catch (IOException e) {
throw new UncheckedIOException("Failed to load " + url + ": " + e, e);
}

resources.put(key,wrapUp(key.length()>0 ? key.substring(1) : "",props));
resources.put(key,wrapUp(key.length()>0 ? key.substring(1) : "", props));
return props;
}

Expand Down
@@ -0,0 +1,63 @@
package org.kohsuke.stapler.jelly;

import hudson.util.VersionNumber;
import io.jenkins.lib.versionnumber.JavaSpecificationVersion;
import java.net.URL;
import java.util.Locale;
import org.junit.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assume.assumeThat;

public class ResourceBundleTest {

private static final URL RESOURCE_BUNDLE = ResourceBundleTest.class.getResource("/org/kohsuke/stapler/jelly/ResourceBundleTest/index.properties");
private static final String FILE_PATH = RESOURCE_BUNDLE.toExternalForm().replace(".properties", "");
private static final ResourceBundle resourceBundle = new ResourceBundle(FILE_PATH);

@Test
public void format() {
String helloWorld = resourceBundle.format(Locale.ENGLISH, "hello_world");

assertThat(helloWorld, is("Hello, World!"));
}

@Test
public void formatFallsBackToDefaultIfMissing() {
String helloWorld = resourceBundle.format(Locale.FRANCE, "hello_world");

assertThat(helloWorld, is("Hello, World!"));
}

@Test
public void formatLocaleOverrideInPlace() {
String helloWorld = resourceBundle.format(Locale.CANADA, "hello_world");

assertThat(helloWorld, is("Welcome, World!"));
}

@Test
public void formatLocaleNonISO_8859_1() {
String helloWorld = resourceBundle.format(Locale.CHINA, "hello_world");

assertThat(helloWorld, is("你好,世界!简化"));
}

@Test
public void formatLocaleNonISO_8859_1_encoded_with_utf8() {
assumeThat("Requires Java 9+", true, is(JavaSpecificationVersion.forCurrentJVM()
.isNewerThan(new VersionNumber("8"))
));
String helloWorld = resourceBundle.format(Locale.TRADITIONAL_CHINESE, "hello_world");

assertThat(helloWorld, is("你好世界!"));
}

@Test
public void formatLocaleISO_8859_1_high_range_character_invalid_utf_8() {
String helloWorld = resourceBundle.format(Locale.FRANCE, "french");

assertThat(helloWorld, is("Français"));
}
}
@@ -0,0 +1 @@
hello_world=Hello, World!
@@ -0,0 +1 @@
hello_world=Welcome, World!
@@ -0,0 +1 @@
french=Fran�ais
@@ -0,0 +1 @@
hello_world=\u4f60\u597d\uff0c\u4e16\u754c\uff01\u7b80\u5316
@@ -0,0 +1 @@
hello_world=你好世界!

0 comments on commit 3b5035c

Please sign in to comment.