mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Switches CLDR to using metadata provider
This commit is contained in:
parent
7512817b3a
commit
5351d08a29
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.impl;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.classlib.impl.unicode.CLDRReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class FirstDayOfWeekMetadataGenerator extends WeekMetadataGenerator {
|
||||||
|
@Override
|
||||||
|
protected Map<String, Integer> getWeekData(CLDRReader reader) {
|
||||||
|
return reader.getFirstDayMap();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,10 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.impl;
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
|
||||||
import org.teavm.classlib.impl.unicode.CLDRReader;
|
import org.teavm.classlib.impl.unicode.CLDRReader;
|
||||||
import org.teavm.classlib.java.util.LocaleSettingsNativeGenerator;
|
|
||||||
import org.teavm.javascript.ni.Generator;
|
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
@ -46,12 +43,5 @@ public class JCLPlugin implements TeaVMPlugin {
|
||||||
host.add(javacSupport);
|
host.add(javacSupport);
|
||||||
|
|
||||||
host.registerService(CLDRReader.class, new CLDRReader(host.getProperties(), host.getClassLoader()));
|
host.registerService(CLDRReader.class, new CLDRReader(host.getProperties(), host.getClassLoader()));
|
||||||
Generator localeGen = new LocaleSettingsNativeGenerator(host.getClassLoader(), host.getProperties());
|
|
||||||
host.add(new MethodReference("java.util.Calendar", "readWeeksFromCDLR", ValueType.VOID), localeGen);
|
|
||||||
host.add(new MethodReference(CLDRHelper.class.getName(), "readLikelySubtagsFromCLDR", ValueType.VOID),
|
|
||||||
localeGen);
|
|
||||||
host.add(new MethodReference("java.util.Locale", "getDefaultLocale", ValueType.object("java.lang.String")),
|
|
||||||
localeGen);
|
|
||||||
host.add(new MethodReference("java.util.Locale", "readAvailableLocales", ValueType.VOID), localeGen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.impl;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.classlib.impl.unicode.CLDRReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class MinimalDaysInFirstWeekMetadataGenerator extends WeekMetadataGenerator {
|
||||||
|
@Override
|
||||||
|
protected Map<String, Integer> getWeekData(CLDRReader reader) {
|
||||||
|
return reader.getMinDaysMap();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.impl;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.classlib.impl.unicode.CLDRReader;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.platform.metadata.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public abstract class WeekMetadataGenerator implements MetadataGenerator {
|
||||||
|
@Override
|
||||||
|
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||||
|
ResourceMap<IntResource> map = context.createResourceMap();
|
||||||
|
for (Map.Entry<String, Integer> entry : getWeekData(context.getService(CLDRReader.class)).entrySet()) {
|
||||||
|
IntResource valueRes = context.createResource(IntResource.class);
|
||||||
|
valueRes.setValue(entry.getValue());
|
||||||
|
map.put(entry.getKey(), valueRes);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Map<String, Integer> getWeekData(CLDRReader reader);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.impl.unicode;
|
||||||
|
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.platform.metadata.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class AvailableLocalesMetadataGenerator implements MetadataGenerator {
|
||||||
|
@Override
|
||||||
|
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||||
|
CLDRReader reader = context.getService(CLDRReader.class);
|
||||||
|
ResourceArray<StringResource> result = context.createResourceArray();
|
||||||
|
for (String locale : reader.getAvailableLocales()) {
|
||||||
|
StringResource localeRes = context.createResource(StringResource.class);
|
||||||
|
localeRes.setValue(locale);
|
||||||
|
result.add(localeRes);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,11 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.impl.unicode;
|
package org.teavm.classlib.impl.unicode;
|
||||||
|
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.classlib.impl.FirstDayOfWeekMetadataGenerator;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.classlib.impl.MinimalDaysInFirstWeekMetadataGenerator;
|
||||||
import org.teavm.platform.metadata.MetadataProvider;
|
import org.teavm.platform.metadata.*;
|
||||||
import org.teavm.platform.metadata.ResourceMap;
|
|
||||||
import org.teavm.platform.metadata.StringResource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -31,33 +29,20 @@ public class CLDRHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getLikelySubtags(String localeCode) {
|
public static String getLikelySubtags(String localeCode) {
|
||||||
readLikelySubtagsFromCLDR();
|
ResourceMap<StringResource> map = getLikelySubtagsMap();
|
||||||
String subtags = getLikelySubtagsImpl(localeCode);
|
return map.has(localeCode) ? map.get(localeCode).getValue() : localeCode;
|
||||||
return subtags != null ? subtags : localeCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defined by JCLPlugin
|
@MetadataProvider(LikelySubtagsMetadataGenerator.class)
|
||||||
private static native void readLikelySubtagsFromCLDR();
|
private static native ResourceMap<StringResource> getLikelySubtagsMap();
|
||||||
|
|
||||||
@GeneratedBy(CLDRHelperNativeGenerator.class)
|
|
||||||
@PluggableDependency(CLDRHelperNativeGenerator.class)
|
|
||||||
private static native String getLikelySubtagsImpl(String localeCode);
|
|
||||||
|
|
||||||
public static String[] resolveEras(String localeCode) {
|
public static String[] resolveEras(String localeCode) {
|
||||||
readErasFromCLDR();
|
ResourceMap<ResourceArray<StringResource>> map = getErasMap();
|
||||||
String[] eras = getEras(localeCode);
|
ResourceArray<StringResource> arrayRes = map.has(localeCode) ? map.get(localeCode) : map.get("root");
|
||||||
if (eras == null) {
|
return new String[] { arrayRes.get(0).getValue(), arrayRes.get(1).getValue() };
|
||||||
eras = getEras("root");
|
|
||||||
}
|
|
||||||
return eras;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defined by JCLPlugin
|
private static native ResourceMap<ResourceArray<StringResource>> getErasMap();
|
||||||
private static native void readErasFromCLDR();
|
|
||||||
|
|
||||||
@GeneratedBy(CLDRHelperNativeGenerator.class)
|
|
||||||
@PluggableDependency(CLDRHelperNativeGenerator.class)
|
|
||||||
private static native String[] getEras(String localeCode);
|
|
||||||
|
|
||||||
@MetadataProvider(LanguageMetadataGenerator.class)
|
@MetadataProvider(LanguageMetadataGenerator.class)
|
||||||
public static native ResourceMap<ResourceMap<StringResource>> getLanguagesMap();
|
public static native ResourceMap<ResourceMap<StringResource>> getLanguagesMap();
|
||||||
|
@ -67,4 +52,13 @@ public class CLDRHelper {
|
||||||
|
|
||||||
@MetadataProvider(DefaultLocaleMetadataGenerator.class)
|
@MetadataProvider(DefaultLocaleMetadataGenerator.class)
|
||||||
public static native StringResource getDefaultLocale();
|
public static native StringResource getDefaultLocale();
|
||||||
|
|
||||||
|
@MetadataProvider(AvailableLocalesMetadataGenerator.class)
|
||||||
|
public static native ResourceArray<StringResource> getAvailableLocales();
|
||||||
|
|
||||||
|
@MetadataProvider(MinimalDaysInFirstWeekMetadataGenerator.class)
|
||||||
|
public static native ResourceMap<IntResource> getMinimalDaysInFirstWeek();
|
||||||
|
|
||||||
|
@MetadataProvider(FirstDayOfWeekMetadataGenerator.class)
|
||||||
|
public static native ResourceMap<IntResource> getFirstDayOfWeek();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.impl.unicode;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import org.teavm.codegen.SourceWriter;
|
|
||||||
import org.teavm.dependency.DependencyAgent;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class CLDRHelperNativeGenerator implements Generator, DependencyPlugin {
|
|
||||||
@Override
|
|
||||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
|
||||||
switch (method.getMethod().getName()) {
|
|
||||||
case "getLikelySubtagsImpl":
|
|
||||||
method.getResult().propagate("java.lang.String");
|
|
||||||
break;
|
|
||||||
case "getEras":
|
|
||||||
method.getResult().propagate("[java.lang.String;");
|
|
||||||
method.getResult().getArrayItem().propagate("java.lang.String");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
|
||||||
switch (methodRef.getName()) {
|
|
||||||
case "getLikelySubtagsImpl":
|
|
||||||
writer.append("var data = ").appendClass("java.util.Locale").append(".$CLDR.likelySubtags[$rt_ustr(")
|
|
||||||
.append(context.getParameterName(1)).append(")];").softNewLine();
|
|
||||||
writer.append("return data ? $rt_str(data) : null;").softNewLine();
|
|
||||||
break;
|
|
||||||
case "getEras":
|
|
||||||
generateGetArray(context, writer, "eras");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateGetArray(GeneratorContext context, SourceWriter writer, String name) throws IOException {
|
|
||||||
writer.append("var data = ").appendClass("java.util.Locale").append(".$CLDR.").append(name)
|
|
||||||
.append("[$rt_ustr(").append(context.getParameterName(1)).append(")];").softNewLine();
|
|
||||||
writer.append("if (!data) {").indent().softNewLine();
|
|
||||||
writer.append("return null;");
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
writer.append("var result = $rt_createArray(").appendClass("java.lang.String)")
|
|
||||||
.append(", data.length);").softNewLine();
|
|
||||||
writer.append("for (var i = 0; i < data.length; ++i) {").indent().softNewLine();
|
|
||||||
writer.append("result.data[i] = $rt_str(data[i])").softNewLine();
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
writer.append("return result;").softNewLine();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -201,4 +201,16 @@ public class CLDRReader {
|
||||||
public Set<String> getAvailableCountries() {
|
public Set<String> getAvailableCountries() {
|
||||||
return Collections.unmodifiableSet(availableCountries);
|
return Collections.unmodifiableSet(availableCountries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, Integer> getMinDaysMap() {
|
||||||
|
return Collections.unmodifiableMap(minDaysMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Integer> getFirstDayMap() {
|
||||||
|
return Collections.unmodifiableMap(firstDayMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getLikelySubtags() {
|
||||||
|
return Collections.unmodifiableMap(likelySubtags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.impl.unicode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.platform.metadata.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class LikelySubtagsMetadataGenerator implements MetadataGenerator {
|
||||||
|
@Override
|
||||||
|
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||||
|
CLDRReader reader = context.getService(CLDRReader.class);
|
||||||
|
ResourceMap<StringResource> map = context.createResourceMap();
|
||||||
|
for (Map.Entry<String, String> entry : reader.getLikelySubtags().entrySet()) {
|
||||||
|
StringResource subtagRes = context.createResource(StringResource.class);
|
||||||
|
subtagRes.setValue(entry.getValue());
|
||||||
|
map.put(entry.getKey(), subtagRes);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 java.io.IOException;
|
|
||||||
import org.teavm.codegen.SourceWriter;
|
|
||||||
import org.teavm.javascript.ni.Generator;
|
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
|
||||||
import org.teavm.model.MethodReference;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class CalendarNativeGenerator implements Generator {
|
|
||||||
@Override
|
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
|
||||||
switch (methodRef.getName()) {
|
|
||||||
case "getFirstDayOfWeek":
|
|
||||||
generateWeekMethod(context, writer, "firstDay");
|
|
||||||
break;
|
|
||||||
case "getMinimalDaysInFirstWeek":
|
|
||||||
generateWeekMethod(context, writer, "minDays");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateWeekMethod(GeneratorContext context, SourceWriter writer, String property)
|
|
||||||
throws IOException {
|
|
||||||
writer.append("var result = ").appendClass("java.util.Locale").append(".$CLDR.").append(property)
|
|
||||||
.append("[$rt_ustr(").append(context.getParameterName(1)).append(")];").softNewLine();
|
|
||||||
writer.append("return result ? result : -1;").softNewLine();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 java.io.IOException;
|
|
||||||
import org.teavm.codegen.SourceWriter;
|
|
||||||
import org.teavm.dependency.DependencyAgent;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class LocaleNativeGenerator implements Generator, DependencyPlugin {
|
|
||||||
@Override
|
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
|
||||||
switch (methodRef.getName()) {
|
|
||||||
case "getAvailableLocaleStrings":
|
|
||||||
generateAvailableLocales(writer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateAvailableLocales(SourceWriter writer) throws IOException {
|
|
||||||
writer.append("var locales = ").appendClass("java.util.Locale").append(".$CLDR.availableLocales;")
|
|
||||||
.softNewLine();
|
|
||||||
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] = $rt_str(locales[i]);").softNewLine();
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
writer.append("return array;").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
|
||||||
switch (method.getMethod().getName()) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,276 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipInputStream;
|
|
||||||
import org.teavm.codegen.SourceWriter;
|
|
||||||
import org.teavm.javascript.Renderer;
|
|
||||||
import org.teavm.javascript.ni.Generator;
|
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
|
||||||
import org.teavm.model.MethodReference;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class LocaleSettingsNativeGenerator implements Generator {
|
|
||||||
private ClassLoader classLoader;
|
|
||||||
private Properties properties;
|
|
||||||
private Map<String, LocaleInfo> knownLocales = new LinkedHashMap<>();
|
|
||||||
private Map<String, Integer> minDaysMap = new LinkedHashMap<>();
|
|
||||||
private Map<String, Integer> firstDayMap = new LinkedHashMap<>();
|
|
||||||
private Map<String, String> likelySubtags = new LinkedHashMap<>();
|
|
||||||
private Set<String> availableLocales = new LinkedHashSet<>();
|
|
||||||
private Set<String> availableLanguages = new LinkedHashSet<>();
|
|
||||||
private Set<String> availableCountries = new LinkedHashSet<>();
|
|
||||||
private boolean initialized;
|
|
||||||
|
|
||||||
public LocaleSettingsNativeGenerator(ClassLoader classLoader, Properties properties) {
|
|
||||||
this.classLoader = classLoader;
|
|
||||||
this.properties = properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void init() {
|
|
||||||
if (!initialized) {
|
|
||||||
initialized = true;
|
|
||||||
findAvailableLocales();
|
|
||||||
readCLDR();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void findAvailableLocales() {
|
|
||||||
String availableLocalesString = properties.getProperty("java.util.Locale.available", "en_EN").trim();
|
|
||||||
for (String locale : Arrays.asList(availableLocalesString.split(" *, *"))) {
|
|
||||||
int countryIndex = locale.indexOf('_');
|
|
||||||
if (countryIndex > 0) {
|
|
||||||
String language = locale.substring(0, countryIndex);
|
|
||||||
String country = locale.substring(countryIndex + 1);
|
|
||||||
availableLocales.add(language + "-" + country);
|
|
||||||
availableLocales.add(language);
|
|
||||||
availableLanguages.add(language);
|
|
||||||
availableCountries.add(country);
|
|
||||||
} else {
|
|
||||||
availableLocales.add(locale);
|
|
||||||
availableLanguages.add(locale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readCLDR() {
|
|
||||||
try (ZipInputStream input = new ZipInputStream(classLoader.getResourceAsStream(
|
|
||||||
"org/teavm/classlib/impl/unicode/cldr-json.zip"))) {
|
|
||||||
while (true) {
|
|
||||||
ZipEntry entry = input.getNextEntry();
|
|
||||||
if (entry == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!entry.getName().endsWith(".json")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (entry.getName().equals("supplemental/weekData.json")) {
|
|
||||||
readWeekData(input);
|
|
||||||
continue;
|
|
||||||
} else if (entry.getName().equals("supplemental/likelySubtags.json")) {
|
|
||||||
readLikelySubtags(input);
|
|
||||||
}
|
|
||||||
int objectIndex = entry.getName().lastIndexOf('/');
|
|
||||||
String objectName = entry.getName().substring(objectIndex + 1);
|
|
||||||
String localeName = entry.getName().substring(0, objectIndex);
|
|
||||||
if (localeName.startsWith("/")) {
|
|
||||||
localeName = localeName.substring(1);
|
|
||||||
}
|
|
||||||
if (!localeName.equals("root") && !availableLocales.contains(localeName)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
LocaleInfo localeInfo = knownLocales.get(localeName);
|
|
||||||
if (localeInfo == null) {
|
|
||||||
localeInfo = new LocaleInfo();
|
|
||||||
knownLocales.put(localeName, localeInfo);
|
|
||||||
}
|
|
||||||
switch (objectName) {
|
|
||||||
case "languages.json":
|
|
||||||
readLanguages(localeName, localeInfo, input);
|
|
||||||
break;
|
|
||||||
case "territories.json":
|
|
||||||
readCountries(localeName, localeInfo, input);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Error reading CLDR file", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readLanguages(String localeCode, LocaleInfo locale, InputStream input) {
|
|
||||||
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
|
|
||||||
JsonObject languagesJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
|
|
||||||
.get("localeDisplayNames").getAsJsonObject().get("languages").getAsJsonObject();
|
|
||||||
for (Map.Entry<String, JsonElement> property : languagesJson.entrySet()) {
|
|
||||||
String language = property.getKey();
|
|
||||||
if (availableLanguages.contains(language)) {
|
|
||||||
locale.languages.put(language, property.getValue().getAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readCountries(String localeCode, LocaleInfo locale, InputStream input) {
|
|
||||||
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
|
|
||||||
JsonObject countriesJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
|
|
||||||
.get("localeDisplayNames").getAsJsonObject().get("territories").getAsJsonObject();
|
|
||||||
for (Map.Entry<String, JsonElement> property : countriesJson.entrySet()) {
|
|
||||||
String country = property.getKey();
|
|
||||||
if (availableCountries.contains(country)) {
|
|
||||||
locale.territories.put(country, property.getValue().getAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readWeekData(InputStream input) {
|
|
||||||
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
|
|
||||||
JsonObject weekJson = root.get("supplemental").getAsJsonObject().get("weekData").getAsJsonObject();
|
|
||||||
JsonObject minDaysJson = weekJson.get("minDays").getAsJsonObject();
|
|
||||||
for (Map.Entry<String, JsonElement> property : minDaysJson.entrySet()) {
|
|
||||||
minDaysMap.put(property.getKey(), property.getValue().getAsInt());
|
|
||||||
}
|
|
||||||
JsonObject firstDayJson = weekJson.get("firstDay").getAsJsonObject();
|
|
||||||
for (Map.Entry<String, JsonElement> property : firstDayJson.entrySet()) {
|
|
||||||
firstDayMap.put(property.getKey(), getNumericDay(property.getValue().getAsString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readLikelySubtags(InputStream input) {
|
|
||||||
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
|
|
||||||
JsonObject likelySubtagsJson = root.get("supplemental").getAsJsonObject().get("likelySubtags")
|
|
||||||
.getAsJsonObject();
|
|
||||||
for (Map.Entry<String, JsonElement> property : likelySubtagsJson.entrySet()) {
|
|
||||||
likelySubtags.put(property.getKey(), property.getValue().getAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getNumericDay(String day) {
|
|
||||||
switch (day) {
|
|
||||||
case "sun":
|
|
||||||
return 1;
|
|
||||||
case "mon":
|
|
||||||
return 2;
|
|
||||||
case "tue":
|
|
||||||
return 3;
|
|
||||||
case "wed":
|
|
||||||
return 4;
|
|
||||||
case "thu":
|
|
||||||
return 5;
|
|
||||||
case "fri":
|
|
||||||
return 6;
|
|
||||||
case "sat":
|
|
||||||
return 7;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Can't recognize day name: " + day);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
|
||||||
init();
|
|
||||||
switch (methodRef.getName()) {
|
|
||||||
case "readWeeksFromCDLR":
|
|
||||||
generateReadWeeksFromCDLR(writer);
|
|
||||||
break;
|
|
||||||
case "readLikelySubtagsFromCLDR":
|
|
||||||
generateReadLikelySubtagsFromCLDR(writer);
|
|
||||||
break;
|
|
||||||
case "readAvailableLocales":
|
|
||||||
generateReadAvailableLocales(writer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateDefender(SourceWriter writer, String property) throws IOException {
|
|
||||||
writer.append("if (").appendClass("java.util.Locale").append(".$CLDR.").append(property)
|
|
||||||
.append(")").ws().append("{").indent().softNewLine();
|
|
||||||
writer.append("return;").softNewLine();
|
|
||||||
writer.outdent().append("}").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateReadAvailableLocales(SourceWriter writer) throws IOException {
|
|
||||||
generateDefender(writer, "availableLocales");
|
|
||||||
writer.appendClass("java.util.Locale").append(".$CLDR.availableLocales = [");
|
|
||||||
boolean first = true;
|
|
||||||
for (String locale : availableLocales) {
|
|
||||||
if (!first) {
|
|
||||||
writer.append(',').ws();
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
writer.append('"').append(Renderer.escapeString(locale)).append('"');
|
|
||||||
}
|
|
||||||
writer.append("];").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateReadWeeksFromCDLR(SourceWriter writer) throws IOException {
|
|
||||||
generateDefender(writer, "minDays");
|
|
||||||
writer.appendClass("java.util.Locale").append(".$CLDR.minDays = {").indent().softNewLine();
|
|
||||||
boolean first = true;
|
|
||||||
for (Map.Entry<String, Integer> entry : minDaysMap.entrySet()) {
|
|
||||||
if (!first) {
|
|
||||||
writer.append(",").softNewLine();
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
writer.append('"').append(Renderer.escapeString(entry.getKey())).append('"').ws().append(':')
|
|
||||||
.ws().append(entry.getValue());
|
|
||||||
}
|
|
||||||
writer.outdent().append("};").softNewLine();
|
|
||||||
|
|
||||||
writer.appendClass("java.util.Locale").append(".$CLDR.firstDay = {").indent().softNewLine();
|
|
||||||
first = true;
|
|
||||||
for (Map.Entry<String, Integer> entry : firstDayMap.entrySet()) {
|
|
||||||
if (!first) {
|
|
||||||
writer.append(",").softNewLine();
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
writer.append('"').append(Renderer.escapeString(entry.getKey())).append('"').ws().append(':')
|
|
||||||
.ws().append(entry.getValue());
|
|
||||||
}
|
|
||||||
writer.outdent().append("};").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateReadLikelySubtagsFromCLDR(SourceWriter writer) throws IOException {
|
|
||||||
generateDefender(writer, "likelySubtags");
|
|
||||||
writer.appendClass("java.util.Locale").append(".$CLDR.likelySubtags = {").indent().softNewLine();
|
|
||||||
boolean first = true;
|
|
||||||
for (Map.Entry<String, String> entry : likelySubtags.entrySet()) {
|
|
||||||
if (!first) {
|
|
||||||
writer.append(",").softNewLine();
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
writer.append('"').append(Renderer.escapeString(entry.getKey())).append('"').ws().append(':')
|
|
||||||
.ws().append('"').append(Renderer.escapeString(entry.getValue())).append('"');
|
|
||||||
}
|
|
||||||
writer.outdent().append("};").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class LocaleInfo {
|
|
||||||
Map<String, String> languages = new LinkedHashMap<>();
|
|
||||||
Map<String, String> territories = new LinkedHashMap<>();
|
|
||||||
String[] eras;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,7 +36,8 @@ import org.teavm.classlib.impl.unicode.CLDRHelper;
|
||||||
import org.teavm.classlib.java.io.TSerializable;
|
import org.teavm.classlib.java.io.TSerializable;
|
||||||
import org.teavm.classlib.java.lang.TCloneable;
|
import org.teavm.classlib.java.lang.TCloneable;
|
||||||
import org.teavm.classlib.java.lang.TComparable;
|
import org.teavm.classlib.java.lang.TComparable;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.platform.metadata.IntResource;
|
||||||
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
|
||||||
public abstract class TCalendar implements TSerializable, TCloneable, TComparable<TCalendar> {
|
public abstract class TCalendar implements TSerializable, TCloneable, TComparable<TCalendar> {
|
||||||
protected boolean areFieldsSet;
|
protected boolean areFieldsSet;
|
||||||
|
@ -154,14 +155,10 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
|
||||||
isSet = new boolean[FIELD_COUNT];
|
isSet = new boolean[FIELD_COUNT];
|
||||||
areFieldsSet = isTimeSet = false;
|
areFieldsSet = isTimeSet = false;
|
||||||
setLenient(true);
|
setLenient(true);
|
||||||
readWeeksFromCDLR();
|
|
||||||
setFirstDayOfWeek(resolveFirstDayOfWeek(locale));
|
setFirstDayOfWeek(resolveFirstDayOfWeek(locale));
|
||||||
setMinimalDaysInFirstWeek(resolveMinimalDaysInFirstWeek(locale));
|
setMinimalDaysInFirstWeek(resolveMinimalDaysInFirstWeek(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generated by JCLPlugin
|
|
||||||
private static native void readWeeksFromCDLR();
|
|
||||||
|
|
||||||
private static String resolveCountry(TLocale locale) {
|
private static String resolveCountry(TLocale locale) {
|
||||||
String country = locale.getCountry();
|
String country = locale.getCountry();
|
||||||
if (country.isEmpty()) {
|
if (country.isEmpty()) {
|
||||||
|
@ -174,28 +171,16 @@ public abstract class TCalendar implements TSerializable, TCloneable, TComparabl
|
||||||
|
|
||||||
private static int resolveFirstDayOfWeek(TLocale locale) {
|
private static int resolveFirstDayOfWeek(TLocale locale) {
|
||||||
String country = resolveCountry(locale);
|
String country = resolveCountry(locale);
|
||||||
int day = getFirstDayOfWeek(country);
|
ResourceMap<IntResource> dayMap = CLDRHelper.getFirstDayOfWeek();
|
||||||
if (day < 0) {
|
return dayMap.has(country) ? dayMap.get(country).getValue() : dayMap.get("001").getValue();
|
||||||
day = getFirstDayOfWeek("001");
|
|
||||||
}
|
|
||||||
return day;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(CalendarNativeGenerator.class)
|
|
||||||
private static native int getFirstDayOfWeek(String localeCode);
|
|
||||||
|
|
||||||
private static int resolveMinimalDaysInFirstWeek(TLocale locale) {
|
private static int resolveMinimalDaysInFirstWeek(TLocale locale) {
|
||||||
String country = resolveCountry(locale);
|
String country = resolveCountry(locale);
|
||||||
int days = getMinimalDaysInFirstWeek(country);
|
ResourceMap<IntResource> dayMap = CLDRHelper.getMinimalDaysInFirstWeek();
|
||||||
if (days < 0) {
|
return dayMap.has(country) ? dayMap.get(country).getValue() : dayMap.get("001").getValue();
|
||||||
days = getMinimalDaysInFirstWeek("001");
|
|
||||||
}
|
|
||||||
return days;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(CalendarNativeGenerator.class)
|
|
||||||
private static native int getMinimalDaysInFirstWeek(String localeCode);
|
|
||||||
|
|
||||||
abstract public void add(int field, int value);
|
abstract public void add(int field, int value);
|
||||||
|
|
||||||
public boolean after(Object calendar) {
|
public boolean after(Object calendar) {
|
||||||
|
|
|
@ -36,8 +36,7 @@ import java.util.Arrays;
|
||||||
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
||||||
import org.teavm.classlib.java.io.TSerializable;
|
import org.teavm.classlib.java.io.TSerializable;
|
||||||
import org.teavm.classlib.java.lang.TCloneable;
|
import org.teavm.classlib.java.lang.TCloneable;
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.platform.metadata.ResourceArray;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
|
||||||
import org.teavm.platform.metadata.ResourceMap;
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
import org.teavm.platform.metadata.StringResource;
|
import org.teavm.platform.metadata.StringResource;
|
||||||
|
|
||||||
|
@ -77,9 +76,6 @@ public final class TLocale implements TCloneable, TSerializable {
|
||||||
private transient String languageCode;
|
private transient String languageCode;
|
||||||
private transient String variantCode;
|
private transient String variantCode;
|
||||||
|
|
||||||
// Redefined by JCLPlugin
|
|
||||||
private static native void readAvailableLocales();
|
|
||||||
|
|
||||||
public TLocale(String language) {
|
public TLocale(String language) {
|
||||||
this(language, "", "");
|
this(language, "", "");
|
||||||
}
|
}
|
||||||
|
@ -126,12 +122,11 @@ public final class TLocale implements TCloneable, TSerializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TLocale[] getAvailableLocales() {
|
public static TLocale[] getAvailableLocales() {
|
||||||
readAvailableLocales();
|
|
||||||
if (availableLocales == null) {
|
if (availableLocales == null) {
|
||||||
String[] strings = getAvailableLocaleStrings();
|
ResourceArray<StringResource> strings = CLDRHelper.getAvailableLocales();
|
||||||
availableLocales = new TLocale[strings.length];
|
availableLocales = new TLocale[strings.size()];
|
||||||
for (int i = 0; i < strings.length; ++i) {
|
for (int i = 0; i < strings.size(); ++i) {
|
||||||
String string = strings[i];
|
String string = strings.get(i).getValue();
|
||||||
int countryIndex = string.indexOf('-');
|
int countryIndex = string.indexOf('-');
|
||||||
if (countryIndex > 0) {
|
if (countryIndex > 0) {
|
||||||
availableLocales[i] = new TLocale(string.substring(0, countryIndex),
|
availableLocales[i] = new TLocale(string.substring(0, countryIndex),
|
||||||
|
@ -144,10 +139,6 @@ public final class TLocale implements TCloneable, TSerializable {
|
||||||
return Arrays.copyOf(availableLocales, availableLocales.length);
|
return Arrays.copyOf(availableLocales, availableLocales.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(LocaleNativeGenerator.class)
|
|
||||||
@PluggableDependency(LocaleNativeGenerator.class)
|
|
||||||
private static native String[] getAvailableLocaleStrings();
|
|
||||||
|
|
||||||
public String getCountry() {
|
public String getCountry() {
|
||||||
return countryCode;
|
return countryCode;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user