diff --git a/teavm-classlib/pom.xml b/teavm-classlib/pom.xml
index 4c97ebc99..199365cb0 100644
--- a/teavm-classlib/pom.xml
+++ b/teavm-classlib/pom.xml
@@ -61,6 +61,9 @@
false
1
+
+ en, en_US, en_GB, ru, ru_RU
+
diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleNativeGenerator.java
index b8de954cf..2ec52ee30 100644
--- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleNativeGenerator.java
+++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleNativeGenerator.java
@@ -17,6 +17,9 @@ package org.teavm.classlib.java.util;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;
+import org.teavm.dependency.DependencyChecker;
+import org.teavm.dependency.DependencyPlugin;
+import org.teavm.dependency.MethodDependency;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.MethodReference;
@@ -25,7 +28,7 @@ import org.teavm.model.MethodReference;
*
* @author Alexey Andreev
*/
-public class LocaleNativeGenerator implements Generator {
+public class LocaleNativeGenerator implements Generator, DependencyPlugin {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
@@ -37,11 +40,12 @@ public class LocaleNativeGenerator implements Generator {
break;
case "getDisplayLanguage":
writer.append("var result = ").appendClass("java.util.Locale").append(".$CLDR[$rt_ustr(")
- .append(context.getParameterName(1)).append(")].languages[$rt_ustr(")
- .append(context.getParameterName(2)).append(")];").softNewLine();
+ .append(context.getParameterName(1)).append(")];").softNewLine();
+ writer.append("result = result ? result.languages[$rt_ustr(")
+ .append(context.getParameterName(2)).append(")] : undefined;").softNewLine();
writer.append("return result ? $rt_str(result) : null;").softNewLine();
break;
- case "getAvailableLocales":
+ case "getAvailableLocaleStrings":
generateAvailableLocales(writer);
break;
}
@@ -52,6 +56,23 @@ public class LocaleNativeGenerator implements Generator {
writer.append("var array = $rt_createArray(").appendClass("java.lang.String").append(", locales);")
.softNewLine();
writer.append("for (var i = 0; i < locales.length; ++i) {").indent().softNewLine();
- writer.append("array.data[i] = locales[i];");
+ writer.append("array.data[i] = $rt_str(locales[i]);").softNewLine();
+ writer.outdent().append("}").softNewLine();
+ writer.append("return array;").softNewLine();
+ }
+
+ @Override
+ public void methodAchieved(DependencyChecker checker, MethodDependency method) {
+ switch (method.getMethod().getName()) {
+ case "getDefaultLocale":
+ case "getDisplayCountry":
+ case "getDisplayLanguage":
+ method.getResult().propagate("java.lang.String");
+ break;
+ case "getAvailableLocaleStrings":
+ method.getResult().propagate("[java.lang.String");
+ method.getResult().getArrayItem().propagate("java.lang.String");
+ break;
+ }
}
}
diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleSettingsNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleSettingsNativeGenerator.java
index d0a75cd14..a8b74194a 100644
--- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleSettingsNativeGenerator.java
+++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/LocaleSettingsNativeGenerator.java
@@ -39,12 +39,19 @@ public class LocaleSettingsNativeGenerator implements Generator {
private Set availableLocales = new LinkedHashSet<>();
private Set availableLanguages = new LinkedHashSet<>();
private Set availableCountries = new LinkedHashSet<>();
+ private boolean initialized;
public LocaleSettingsNativeGenerator(ClassLoader classLoader, Properties properties) {
this.classLoader = classLoader;
this.properties = properties;
- findAvailableLocales();
- readCLDR();
+ }
+
+ private synchronized void init() {
+ if (!initialized) {
+ initialized = true;
+ findAvailableLocales();
+ readCLDR();
+ }
}
private void findAvailableLocales() {
@@ -67,7 +74,7 @@ public class LocaleSettingsNativeGenerator implements Generator {
private void readCLDR() {
try (ZipInputStream input = new ZipInputStream(classLoader.getResourceAsStream(
- "/org/teavm/classlib/impl/unicode/cldr-json.zip"))) {
+ "org/teavm/classlib/impl/unicode/cldr-json.zip"))) {
while (true) {
ZipEntry entry = input.getNextEntry();
if (entry == null) {
@@ -82,6 +89,9 @@ public class LocaleSettingsNativeGenerator implements Generator {
if (localeName.startsWith("/")) {
localeName = localeName.substring(1);
}
+ if (!availableLocales.contains(localeName)) {
+ continue;
+ }
LocaleInfo localeInfo = knownLocales.get(localeName);
if (localeInfo == null) {
localeInfo = new LocaleInfo();
@@ -127,6 +137,7 @@ public class LocaleSettingsNativeGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
+ init();
switch (methodRef.getName()) {
case "readCLDR":
generateReadCLDR(writer);
@@ -138,7 +149,43 @@ public class LocaleSettingsNativeGenerator implements Generator {
}
private void generateReadCLDR(SourceWriter writer) throws IOException {
- writer.appendClass("java.util.Locale").append(".$CLDR = {");
+ writer.appendClass("java.util.Locale").append(".$CLDR = {").indent().softNewLine();
+ boolean firstLocale = true;
+ for (Map.Entry entry : knownLocales.entrySet()) {
+ if (!firstLocale) {
+ writer.append(",").softNewLine();
+ }
+ firstLocale = false;
+ writer.append('"').append(Renderer.escapeString(entry.getKey())).append('"').ws().append(":").ws()
+ .append('{').indent().softNewLine();
+
+ writer.append("\"languages\"").ws().append(':').ws().append('{').indent().softNewLine();
+ boolean first = true;
+ for (Map.Entry langEntry : entry.getValue().languages.entrySet()) {
+ if (!first) {
+ writer.append(',').softNewLine();
+ }
+ first = false;
+ writer.append('"').append(Renderer.escapeString(langEntry.getKey())).append('"').ws().append(':')
+ .ws().append('"').append(Renderer.escapeString(langEntry.getValue())).append('"');
+ }
+ writer.outdent().append("},").softNewLine();
+
+ writer.append("\"territories\"").ws().append(':').ws().append('{').indent().softNewLine();
+ first = true;
+ for (Map.Entry langEntry : entry.getValue().territories.entrySet()) {
+ if (!first) {
+ writer.append(',').softNewLine();
+ }
+ first = false;
+ writer.append('"').append(Renderer.escapeString(langEntry.getKey())).append('"').ws().append(':')
+ .ws().append('"').append(Renderer.escapeString(langEntry.getValue())).append('"');
+ }
+ writer.outdent().append('}');
+
+ writer.outdent().append('}');
+ }
+ writer.outdent().append("}").softNewLine();
}
private void generateGetDefaultLocale(SourceWriter writer) throws IOException {
diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TLocale.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TLocale.java
index 1607f7ab0..18625a98d 100644
--- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TLocale.java
+++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TLocale.java
@@ -35,6 +35,7 @@ package org.teavm.classlib.java.util;
import java.util.Arrays;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.TCloneable;
+import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.GeneratedBy;
public final class TLocale implements TCloneable, TSerializable {
@@ -75,6 +76,7 @@ public final class TLocale implements TCloneable, TSerializable {
private transient String variantCode;
// Redefined by JCLPlugin
+ @PluggableDependency(LocaleNativeGenerator.class)
private static native String getDefaultLocale();
// Redefined by JCLPlugin
@@ -127,12 +129,24 @@ public final class TLocale implements TCloneable, TSerializable {
public static TLocale[] getAvailableLocales() {
if (availableLocales == null) {
- availableLocales = getAvailableLocales();
+ String[] strings = getAvailableLocaleStrings();
+ availableLocales = new TLocale[strings.length];
+ for (int i = 0; i < strings.length; ++i) {
+ String string = strings[i];
+ int countryIndex = string.indexOf('-');
+ if (countryIndex > 0) {
+ availableLocales[i] = new TLocale(string.substring(0, countryIndex),
+ string.substring(countryIndex));
+ } else {
+ availableLocales[i] = new TLocale(string);
+ }
+ }
}
return Arrays.copyOf(availableLocales, availableLocales.length);
}
@GeneratedBy(LocaleNativeGenerator.class)
+ @PluggableDependency(LocaleNativeGenerator.class)
private static native String[] getAvailableLocaleStrings();
public String getCountry() {
@@ -156,6 +170,7 @@ public final class TLocale implements TCloneable, TSerializable {
}
@GeneratedBy(LocaleNativeGenerator.class)
+ @PluggableDependency(LocaleNativeGenerator.class)
private static native String getDisplayCountry(String localeName, String country);
public final String getDisplayLanguage() {
@@ -163,14 +178,15 @@ public final class TLocale implements TCloneable, TSerializable {
}
public String getDisplayLanguage(TLocale locale) {
- String result = getDisplayLanguage(locale.getLanguage() + "_" + locale.getCountry(), countryCode);
+ String result = getDisplayLanguage(locale.getLanguage() + "-" + locale.getCountry(), languageCode);
if (result == null) {
- result = getDisplayLanguage(locale.getLanguage(), countryCode);
+ result = getDisplayLanguage(locale.getLanguage(), languageCode);
}
- return result != null ? result : countryCode;
+ return result != null ? result : languageCode;
}
@GeneratedBy(LocaleNativeGenerator.class)
+ @PluggableDependency(LocaleNativeGenerator.class)
private static native String getDisplayLanguage(String localeName, String country);
public final String getDisplayName() {
diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/LocaleTest.java b/teavm-classlib/src/test/java/org/teavm/classlib/java/util/LocaleTest.java
new file mode 100644
index 000000000..6557f8175
--- /dev/null
+++ b/teavm-classlib/src/test/java/org/teavm/classlib/java/util/LocaleTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 Alexey Andreev.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.teavm.classlib.java.util;
+
+import static org.junit.Assert.*;
+import java.util.Locale;
+import org.junit.Test;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class LocaleTest {
+ @Test
+ public void availableLocalesFound() {
+ assertNotEquals(0, Locale.getAvailableLocales().length);
+ }
+
+ @Test
+ public void localeNamesProvided() {
+ Locale english = new Locale("en", "US");
+ Locale russian = new Locale("ru", "RU");
+ assertEquals("English", english.getDisplayLanguage(english));
+ assertEquals("Russian", russian.getDisplayLanguage(english));
+ assertEquals("английский", english.getDisplayLanguage(russian));
+ assertEquals("русский", russian.getDisplayLanguage(russian));
+ }
+}
diff --git a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
index b0794db1c..1bb62251d 100644
--- a/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
+++ b/teavm-maven-plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
@@ -100,6 +100,9 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
private List additionalScriptLocalPaths = new ArrayList<>();
+ @Parameter
+ private Properties properties;
+
public void setProject(MavenProject project) {
this.project = project;
}
@@ -140,6 +143,10 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
this.transformers = transformers;
}
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (System.getProperty("maven.test.skip", "false").equals("true") ||
@@ -330,6 +337,7 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
.setClassSource(classSource)
.setExecutor(executor)
.build();
+ vm.setProperties(properties);
vm.setMinifying(minifying);
vm.installPlugins();
new TestExceptionPlugin().install(vm);