Merge "Use Locale to process text resources"
commit
f9d8ba3ada
|
@ -3656,7 +3656,7 @@ public final class KeyboardTextsTable {
|
|||
|
||||
private static final Object[] LOCALES_AND_TEXTS = {
|
||||
// "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */
|
||||
"DEFAULT", TEXTS_DEFAULT, /* 168/168 default */
|
||||
"DEFAULT", TEXTS_DEFAULT, /* 168/168 DEFAULT */
|
||||
"af" , TEXTS_af, /* 7/ 12 Afrikaans */
|
||||
"ar" , TEXTS_ar, /* 55/107 Arabic */
|
||||
"az_AZ" , TEXTS_az_AZ, /* 8/ 17 Azerbaijani (Azerbaijan) */
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.net.URL;
|
|||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
|
@ -86,23 +87,23 @@ public final class JarUtils {
|
|||
}
|
||||
|
||||
// The locale is taken from string resource jar entry name (values-<locale>/)
|
||||
// or {@link LocaleUtils#DEFAULT_LOCALE_KEY} for the default string resource
|
||||
// or {@link LocaleUtils#DEFAULT_LOCALE} for the default string resource
|
||||
// directory (values/).
|
||||
public static String getLocaleFromEntryName(final String jarEntryName) {
|
||||
public static Locale getLocaleFromEntryName(final String jarEntryName) {
|
||||
final String dirName = jarEntryName.substring(0, jarEntryName.lastIndexOf('/'));
|
||||
final int pos = dirName.lastIndexOf('/');
|
||||
final String parentName = (pos >= 0) ? dirName.substring(pos + 1) : dirName;
|
||||
final int localePos = parentName.indexOf('-');
|
||||
if (localePos < 0) {
|
||||
// Default resource name.
|
||||
return LocaleUtils.DEFAULT_LOCALE_KEY;
|
||||
return LocaleUtils.DEFAULT_LOCALE;
|
||||
}
|
||||
final String locale = parentName.substring(localePos + 1);
|
||||
final int regionPos = locale.indexOf("-r");
|
||||
final String localeStr = parentName.substring(localePos + 1);
|
||||
final int regionPos = localeStr.indexOf("-r");
|
||||
if (regionPos < 0) {
|
||||
return locale;
|
||||
return LocaleUtils.constructLocaleFromString(localeStr);
|
||||
}
|
||||
return locale.replace("-r", "_");
|
||||
return LocaleUtils.constructLocaleFromString(localeStr.replace("-r", "_"));
|
||||
}
|
||||
|
||||
public static void close(final Closeable stream) {
|
||||
|
|
|
@ -26,7 +26,8 @@ import java.util.Locale;
|
|||
* for the make-keyboard-text tool.
|
||||
*/
|
||||
public final class LocaleUtils {
|
||||
public static final String DEFAULT_LOCALE_KEY = "DEFAULT";
|
||||
public static final Locale DEFAULT_LOCALE = Locale.ROOT;
|
||||
private static final String DEFAULT_LOCALE_CODE = "DEFAULT";
|
||||
public static final String NO_LANGUAGE_LOCALE_CODE = "zz";
|
||||
public static final String NO_LANGUAGE_LOCALE_DISPLAY_NAME = "Alphabet";
|
||||
|
||||
|
@ -36,39 +37,131 @@ public final class LocaleUtils {
|
|||
|
||||
private static final HashMap<String, Locale> sLocaleCache = new HashMap<String, Locale>();
|
||||
|
||||
private static final int INDEX_LANGUAGE = 0;
|
||||
private static final int INDEX_SCRIPT = 1;
|
||||
private static final int INDEX_REGION = 2;
|
||||
private static final int ELEMENT_LIMIT = INDEX_REGION + 1;
|
||||
|
||||
/**
|
||||
* Creates a locale from a string specification.
|
||||
*
|
||||
* Locale string is: language(_script)?(_region)?
|
||||
* where: language := [a-zA-Z]{2,3}
|
||||
* script := [a-zA-Z]{4}
|
||||
* region := [a-zA-Z]{2,3}|[0-9]{3}
|
||||
*/
|
||||
public static Locale constructLocaleFromString(final String localeStr) {
|
||||
if (localeStr == null) {
|
||||
return null;
|
||||
}
|
||||
synchronized (sLocaleCache) {
|
||||
Locale retval = sLocaleCache.get(localeStr);
|
||||
if (retval != null) {
|
||||
return retval;
|
||||
if (sLocaleCache.containsKey(localeStr)) {
|
||||
return sLocaleCache.get(localeStr);
|
||||
}
|
||||
final String[] localeParams = localeStr.split("_", 3);
|
||||
// TODO: Use JDK 7 Locale.Builder to handle a script name.
|
||||
if (localeParams.length == 1) {
|
||||
retval = new Locale(localeParams[0]);
|
||||
} else if (localeParams.length == 2) {
|
||||
retval = new Locale(localeParams[0], localeParams[1]);
|
||||
} else if (localeParams.length == 3) {
|
||||
retval = new Locale(localeParams[0], localeParams[1], localeParams[2]);
|
||||
boolean hasRegion = false;
|
||||
final Locale.Builder builder = new Locale.Builder();
|
||||
final String[] localeElements = localeStr.split("_", ELEMENT_LIMIT);
|
||||
if (localeElements.length > INDEX_LANGUAGE) {
|
||||
final String text = localeElements[INDEX_LANGUAGE];
|
||||
if (isValidLanguage(text)) {
|
||||
builder.setLanguage(text);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown locale format: " + localeStr);
|
||||
}
|
||||
}
|
||||
if (retval != null) {
|
||||
sLocaleCache.put(localeStr, retval);
|
||||
if (localeElements.length > INDEX_SCRIPT) {
|
||||
final String text = localeElements[INDEX_SCRIPT];
|
||||
if (isValidScript(text)) {
|
||||
builder.setScript(text);
|
||||
} else if (isValidRegion(text)) {
|
||||
builder.setRegion(text);
|
||||
hasRegion = true;
|
||||
} else {
|
||||
throw new RuntimeException("Unknown locale format: " + localeStr);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
if (localeElements.length > INDEX_REGION) {
|
||||
final String text = localeElements[INDEX_REGION];
|
||||
if (!hasRegion && isValidRegion(text)) {
|
||||
builder.setRegion(text);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown locale format: " + localeStr);
|
||||
}
|
||||
}
|
||||
final Locale locale = builder.build();
|
||||
sLocaleCache.put(localeStr, locale);
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getLocaleDisplayName(final String localeString) {
|
||||
if (localeString.equals(NO_LANGUAGE_LOCALE_CODE)) {
|
||||
private static final int MIN_LENGTH_OF_LANGUAGE = 2;
|
||||
private static final int MAX_LENGTH_OF_LANGUAGE = 2;
|
||||
private static final int LENGTH_OF_SCRIPT = 4;
|
||||
private static final int MIN_LENGTH_OF_REGION = 2;
|
||||
private static final int MAX_LENGTH_OF_REGION = 2;
|
||||
private static final int LENGTH_OF_AREA_CODE = 3;
|
||||
|
||||
private static boolean isValidLanguage(final String text) {
|
||||
return isAlphabetSequence(text, MIN_LENGTH_OF_LANGUAGE, MAX_LENGTH_OF_LANGUAGE);
|
||||
}
|
||||
|
||||
private static boolean isValidScript(final String text) {
|
||||
return isAlphabetSequence(text, LENGTH_OF_SCRIPT, LENGTH_OF_SCRIPT);
|
||||
}
|
||||
|
||||
private static boolean isValidRegion(final String text) {
|
||||
return isAlphabetSequence(text, MIN_LENGTH_OF_REGION, MAX_LENGTH_OF_REGION)
|
||||
|| isDigitSequence(text, LENGTH_OF_AREA_CODE, LENGTH_OF_AREA_CODE);
|
||||
}
|
||||
|
||||
private static boolean isAlphabetSequence(final String text, final int lower, final int upper) {
|
||||
final int length = text.length();
|
||||
if (length < lower || length > upper) {
|
||||
return false;
|
||||
}
|
||||
for (int index = 0; index < length; index++) {
|
||||
if (!isAsciiAlphabet(text.charAt(index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isDigitSequence(final String text, final int lower, final int upper) {
|
||||
final int length = text.length();
|
||||
if (length < lower || length > upper) {
|
||||
return false;
|
||||
}
|
||||
for (int index = 0; index < length; ++index) {
|
||||
if (!isAsciiDigit(text.charAt(index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isAsciiAlphabet(char c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
private static boolean isAsciiDigit(char c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
public static String getLocaleCode(final Locale locale) {
|
||||
if (locale == DEFAULT_LOCALE) {
|
||||
return DEFAULT_LOCALE_CODE;
|
||||
}
|
||||
return locale.toString();
|
||||
}
|
||||
|
||||
public static String getLocaleDisplayName(final Locale locale) {
|
||||
if (locale == DEFAULT_LOCALE) {
|
||||
return DEFAULT_LOCALE_CODE;
|
||||
}
|
||||
if (locale.getLanguage().equals(NO_LANGUAGE_LOCALE_CODE)) {
|
||||
return NO_LANGUAGE_LOCALE_DISPLAY_NAME;
|
||||
}
|
||||
final Locale locale = constructLocaleFromString(localeString);
|
||||
return locale.getDisplayName(Locale.ENGLISH);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.TreeMap;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
|
@ -60,9 +61,10 @@ public class MoreKeysResources {
|
|||
jar, TEXT_RESOURCE_NAME);
|
||||
for (final String entryName : resourceEntryNames) {
|
||||
final StringResourceMap resMap = new StringResourceMap(entryName);
|
||||
mResourcesMap.put(resMap.mLocale, resMap);
|
||||
mResourcesMap.put(LocaleUtils.getLocaleCode(resMap.mLocale), resMap);
|
||||
}
|
||||
mDefaultResourceMap = mResourcesMap.get(LocaleUtils.DEFAULT_LOCALE_KEY);
|
||||
mDefaultResourceMap = mResourcesMap.get(
|
||||
LocaleUtils.getLocaleCode(LocaleUtils.DEFAULT_LOCALE));
|
||||
|
||||
// Initialize name histogram and names list.
|
||||
final HashMap<String, Integer> nameHistogram = mNameHistogram;
|
||||
|
@ -165,13 +167,13 @@ public class MoreKeysResources {
|
|||
mDefaultResourceMap.setOutputArraySize(outputArraySize);
|
||||
}
|
||||
|
||||
private static String getArrayNameForLocale(final String locale) {
|
||||
return TEXTS_ARRAY_NAME_PREFIX + locale;
|
||||
private static String getArrayNameForLocale(final Locale locale) {
|
||||
return TEXTS_ARRAY_NAME_PREFIX + LocaleUtils.getLocaleCode(locale);
|
||||
}
|
||||
|
||||
private void dumpTexts(final PrintStream out) {
|
||||
for (final StringResourceMap resMap : mResourcesMap.values()) {
|
||||
final String locale = resMap.mLocale;
|
||||
final Locale locale = resMap.mLocale;
|
||||
if (resMap == mDefaultResourceMap) continue;
|
||||
out.format(" /* Locale %s: %s */\n",
|
||||
locale, LocaleUtils.getLocaleDisplayName(locale));
|
||||
|
@ -185,10 +187,11 @@ public class MoreKeysResources {
|
|||
|
||||
private void dumpLocalesMap(final PrintStream out) {
|
||||
for (final StringResourceMap resMap : mResourcesMap.values()) {
|
||||
final String locale = resMap.mLocale;
|
||||
final String localeToDump = locale.equals(LocaleUtils.DEFAULT_LOCALE_KEY)
|
||||
? String.format("\"%s\"", locale)
|
||||
: String.format("\"%s\"%s", locale, " ".substring(locale.length()));
|
||||
final Locale locale = resMap.mLocale;
|
||||
final String localeStr = LocaleUtils.getLocaleCode(locale);
|
||||
final String localeToDump = (locale == LocaleUtils.DEFAULT_LOCALE)
|
||||
? String.format("\"%s\"", localeStr)
|
||||
: String.format("\"%s\"%s", localeStr, " ".substring(localeStr.length()));
|
||||
out.format(" %s, %-12s /* %3d/%3d %s */\n",
|
||||
localeToDump, getArrayNameForLocale(locale) + ",",
|
||||
resMap.getResources().size(), resMap.getOutputArraySize(),
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
@ -34,8 +35,8 @@ import javax.xml.parsers.SAXParser;
|
|||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
public class StringResourceMap {
|
||||
// Locale name.
|
||||
public final String mLocale;
|
||||
// Locale of this string resource map.
|
||||
public final Locale mLocale;
|
||||
// String resource list.
|
||||
private final List<StringResource> mResources;
|
||||
// Name to string resource map.
|
||||
|
|
Loading…
Reference in New Issue