diff options
Diffstat (limited to 'java/src')
16 files changed, 3092 insertions, 230 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index fbb13c25f..fa7ec5cbf 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -60,10 +60,12 @@ public class Key { private static final int LABEL_FLAGS_ALIGN_LEFT = 0x01; private static final int LABEL_FLAGS_ALIGN_RIGHT = 0x02; private static final int LABEL_FLAGS_ALIGN_LEFT_OF_CENTER = 0x08; - private static final int LABEL_FLAGS_LARGE_LETTER = 0x10; - private static final int LABEL_FLAGS_FONT_NORMAL = 0x20; - private static final int LABEL_FLAGS_FONT_MONO_SPACE = 0x40; - public static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80; + private static final int LABEL_FLAGS_FONT_NORMAL = 0x10; + private static final int LABEL_FLAGS_FONT_MONO_SPACE = 0x20; + private static final int LABEL_FLAGS_FOLLOW_KEY_RATIO_MASK = 0x1C0; + private static final int LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO = 0x40; + private static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80; + private static final int LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO = 0xC0; private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100; private static final int LABEL_FLAGS_HAS_POPUP_HINT = 0x200; private static final int LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT = 0x400; @@ -189,11 +191,11 @@ public class Key { * @param row the row that this key belongs to. row's x-coordinate will be the right edge of * this key. * @param parser the XML parser containing the attributes for this key - * @param keyStyles active key styles set * @throws XmlPullParserException */ public Key(Resources res, Keyboard.Params params, Keyboard.Builder.Row row, - XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException { + XmlPullParser parser) throws XmlPullParserException { + final KeyStyles keyStyles = params.mKeyStyles; final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap; final int keyHeight = row.mRowHeight; mVerticalGap = params.mVerticalGap; @@ -210,7 +212,7 @@ public class Key { throw new XmlParseUtils.ParseException( "Unknown key style: " + styleName, parser); } else { - style = KeyStyles.getEmptyKeyStyle(); + style = keyStyles.getEmptyKeyStyle(); } final float keyXPos = row.getKeyX(keyAttr); @@ -498,16 +500,17 @@ public class Key { } public int selectTextSize(int letter, int largeLetter, int label, int hintLabel) { - if (StringUtils.codePointCount(mLabel) > 1 - && (mLabelFlags & (LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO - | LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) { - return label; - } else if ((mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO) != 0) { - return hintLabel; - } else if ((mLabelFlags & LABEL_FLAGS_LARGE_LETTER) != 0) { + switch (mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_RATIO_MASK) { + case LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO: return largeLetter; - } else { + case LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO: return letter; + case LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO: + return label; + case LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO: + return hintLabel; + default: // No follow key ratio flag specified. + return StringUtils.codePointCount(mLabel) == 1 ? letter : label; } } @@ -563,6 +566,12 @@ public class Key { return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_HAS_LABELS) != 0; } + public int getMoreKeyLabelFlags() { + return hasLabelsInMoreKeys() + ? LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO + : LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO; + } + public boolean needsDividersInMoreKeys() { return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_NEEDS_DIVIDERS) != 0; } @@ -709,8 +718,8 @@ public class Key { public static class Spacer extends Key { public Spacer(Resources res, Keyboard.Params params, Keyboard.Builder.Row row, - XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException { - super(res, params, row, parser, keyStyles); + XmlPullParser parser) throws XmlPullParserException { + super(res, params, row, parser); } /** diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 36a988bb6..58225e95d 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -30,8 +30,11 @@ import android.view.InflateException; import com.android.inputmethod.keyboard.internal.KeyStyles; import com.android.inputmethod.keyboard.internal.KeyboardCodesSet; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; +import com.android.inputmethod.keyboard.internal.KeyboardLabelsSet; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.SubtypeLocale; import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.XmlParseUtils; @@ -43,6 +46,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Locale; /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard @@ -240,6 +244,8 @@ public class Keyboard { public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>(); public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); public final KeyboardCodesSet mCodesSet = new KeyboardCodesSet(); + public final KeyboardLabelsSet mLabelsSet = new KeyboardLabelsSet(); + public final KeyStyles mKeyStyles = new KeyStyles(mLabelsSet); public KeyboardLayoutSet.KeysCache mKeysCache; @@ -500,7 +506,6 @@ public class Keyboard { private boolean mLeftEdge; private boolean mTopEdge; private Key mRightEdgeKey = null; - private final KeyStyles mKeyStyles = new KeyStyles(); /** * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. @@ -777,7 +782,20 @@ public class Keyboard { params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0); params.mIconsSet.loadIcons(keyboardAttr); - params.mCodesSet.setLanguage(params.mId.mLocale.getLanguage()); + final String language = params.mId.mLocale.getLanguage(); + params.mCodesSet.setLanguage(language); + params.mLabelsSet.setLanguage(language); + final RunInLocale<Void> job = new RunInLocale<Void>() { + @Override + protected Void job(Resources res) { + params.mLabelsSet.loadStringResources(mContext); + return null; + } + }; + // Null means the current system locale. + final Locale locale = language.equals(SubtypeLocale.NO_LANGUAGE) + ? null : params.mId.mLocale; + job.runInLocale(mResources, locale); final int resourceId = keyboardAttr.getResourceId( R.styleable.Keyboard_touchPositionCorrectionData, 0); @@ -887,7 +905,7 @@ public class Keyboard { XmlParseUtils.checkEndTag(TAG_KEY, parser); if (DEBUG) startEndTag("<%s /> skipped", TAG_KEY); } else { - final Key key = new Key(mResources, mParams, row, parser, mKeyStyles); + final Key key = new Key(mResources, mParams, row, parser); if (DEBUG) { startEndTag("<%s%s %s moreKeys=%s />", TAG_KEY, (key.isEnabled() ? "" : " disabled"), key, @@ -904,8 +922,7 @@ public class Keyboard { XmlParseUtils.checkEndTag(TAG_SPACER, parser); if (DEBUG) startEndTag("<%s /> skipped", TAG_SPACER); } else { - final Key.Spacer spacer = new Key.Spacer( - mResources, mParams, row, parser, mKeyStyles); + final Key.Spacer spacer = new Key.Spacer(mResources, mParams, row, parser); if (DEBUG) startEndTag("<%s />", TAG_SPACER); XmlParseUtils.checkEndTag(TAG_SPACER, parser); endKey(spacer); @@ -1210,7 +1227,7 @@ public class Keyboard { skip ? " skipped" : ""); } if (!skip) - mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser); + mParams.mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser); } finally { keyStyleAttr.recycle(); keyAttrs.recycle(); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java index 51cd90549..803a2948e 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java @@ -29,12 +29,10 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.keyboard.KeyboardLayoutSet.Params.ElementParams; -import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.latin.InputTypeUtils; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.LocaleUtils; -import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SubtypeLocale; @@ -65,9 +63,7 @@ public class KeyboardLayoutSet { private static final String DEFAULT_KEYBOARD_LAYOUT_SET = "qwerty"; private static final char KEYBOARD_LAYOUT_SET_LOCALE_DELIMITER = ':'; - private static final String KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX = "xml/keyboard_layout_set_"; - private static final int DEFAULT_KEYBOARD_LAYOUT_SET_RESOURCE_ID = - R.xml.keyboard_layout_set_qwerty; + private static final String KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX = "keyboard_layout_set_"; private final Context mContext; private final Params mParams; @@ -185,14 +181,7 @@ public class KeyboardLayoutSet { builder.setAutoGenerate(sKeysCache); } final int keyboardXmlId = elementParams.mKeyboardXmlId; - final RunInLocale<Void> job = new RunInLocale<Void>() { - @Override - protected Void job(Resources res) { - builder.load(keyboardXmlId, id); - return null; - } - }; - job.runInLocale(context.getResources(), id.mLocale); + builder.load(keyboardXmlId, id); builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled); builder.setProximityCharsCorrectionEnabled( elementParams.mProximityCharsCorrectionEnabled); @@ -319,21 +308,15 @@ public class KeyboardLayoutSet { throw new RuntimeException("Screen geometry is not specified"); if (mParams.mLocale == null) throw new RuntimeException("KeyboardLayoutSet subtype is not specified"); + final String packageName = mResources.getResourcePackageName( + R.xml.keyboard_layout_set_qwerty); final String keyboardLayoutSetName = mParams.mKeyboardLayoutSetName; - final int xmlId = KeySpecParser.getResourceId( - mResources, keyboardLayoutSetName, DEFAULT_KEYBOARD_LAYOUT_SET_RESOURCE_ID); - final RunInLocale<Void> job = new RunInLocale<Void>() { - @Override - protected Void job(Resources res) { - try { - parseKeyboardLayoutSet(res, xmlId); - } catch (Exception e) { - throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName); - } - return null; - } - }; - job.runInLocale(mResources, mParams.mLocale); + final int xmlId = mResources.getIdentifier(keyboardLayoutSetName, "xml", packageName); + try { + parseKeyboardLayoutSet(mResources, xmlId); + } catch (Exception e) { + throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName); + } return new KeyboardLayoutSet(mContext, mParams); } diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index f8682d8ca..7154086e2 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -332,10 +332,7 @@ public class MoreKeysKeyboard extends Keyboard { @Override public MoreKeysKeyboard build() { final MoreKeysKeyboardParams params = mParams; - // moreKeyFlags == 0 means that the rendered text size will be determined by its - // label's code point count. - final int moreKeyFlags = mParentKey.hasLabelsInMoreKeys() ? 0 - : Key.LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO; + final int moreKeyFlags = mParentKey.getMoreKeyLabelFlags(); final MoreKeySpec[] moreKeys = mParentKey.mMoreKeys; for (int n = 0; n < moreKeys.length; n++) { final MoreKeySpec moreKeySpec = moreKeys[n]; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index 288fb4556..2981a8e5c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -16,7 +16,6 @@ package com.android.inputmethod.keyboard.internal; -import android.content.res.Resources; import android.text.TextUtils; import com.android.inputmethod.keyboard.Keyboard; @@ -27,18 +26,20 @@ import java.util.ArrayList; import java.util.Arrays; /** - * String parser of moreKeys attribute of Key. - * The string is comma separated texts each of which represents one "more key". - * - String resource can be embedded into specification @string/name. This is done before parsing - * comma. + * The string parser of more keys specification. + * The specification is comma separated texts each of which represents one "more key". + * The specification might have label or string resource reference in it. These references are + * expanded before parsing comma. + * - Label reference should be a string representation of label (!label/label_name) + * - String resource reference should be a string representation of resource (!label/resource_name) * Each "more key" specification is one of the following: * - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText). * - Icon followed by keyOutputText or code (!icon/icon_name|!code/code_name) * - Icon should be a string representation of icon (!icon/icon_name). - * - Code should be a code point presented by hexadecimal string prefixed with "0x". - * Or a string representation of code (!code/code_name). + * - Code should be a code point presented by hexadecimal string prefixed with "0x", or a string + * representation of code (!code/code_name). * Special character, comma ',' backslash '\', and bar '|' can be escaped by '\' character. - * Note that the character '@' and '\' are also parsed by XML parser and CSV parser as well. + * Note that the '\' is also parsed by XML parser and CSV parser as well. * See {@link KeyboardIconsSet} about icon_name. */ public class KeySpecParser { @@ -49,10 +50,8 @@ public class KeySpecParser { // Constants for parsing. private static int COMMA = ','; private static final char ESCAPE_CHAR = '\\'; - private static final char PREFIX_AT = '@'; - private static final char SUFFIX_SLASH = '/'; - private static final String PREFIX_STRING = PREFIX_AT + "string" + SUFFIX_SLASH; private static final char LABEL_END = '|'; + private static final String PREFIX_LABEL = "!label/"; private static final String PREFIX_ICON = "!icon/"; private static final String PREFIX_CODE = "!code/"; private static final String PREFIX_HEX = "0x"; @@ -341,17 +340,7 @@ public class KeySpecParser { } } - public static int getResourceId(Resources res, String name, int packageNameResId) { - String packageName = res.getResourcePackageName(packageNameResId); - int resId = res.getIdentifier(name, null, packageName); - if (resId == 0) { - throw new RuntimeException("Unknown resource: " + name); - } - return resId; - } - - private static String resolveStringResource(String rawText, Resources res, - int packageNameResId) { + public static String resolveLabelReference(String rawText, KeyboardLabelsSet labelsSet) { int level = 0; String text = rawText; StringBuilder sb; @@ -362,21 +351,20 @@ public class KeySpecParser { } final int size = text.length(); - if (size < PREFIX_STRING.length()) { + if (size < PREFIX_LABEL.length()) { return text; } sb = null; for (int pos = 0; pos < size; pos++) { final char c = text.charAt(pos); - if (c == PREFIX_AT && text.startsWith(PREFIX_STRING, pos)) { + if (text.startsWith(PREFIX_LABEL, pos) && labelsSet != null) { if (sb == null) { sb = new StringBuilder(text.substring(0, pos)); } - final int end = searchResourceNameEnd(text, pos + PREFIX_STRING.length()); - final String resName = text.substring(pos + 1, end); - final int resId = getResourceId(res, resName, packageNameResId); - sb.append(res.getString(resId)); + final int end = searchLabelNameEnd(text, pos + PREFIX_LABEL.length()); + final String name = text.substring(pos + PREFIX_LABEL.length(), end); + sb.append(labelsSet.getLabel(name)); pos = end - 1; } else if (c == ESCAPE_CHAR) { if (sb != null) { @@ -397,7 +385,7 @@ public class KeySpecParser { return text; } - private static int searchResourceNameEnd(String text, int start) { + private static int searchLabelNameEnd(String text, int start) { final int size = text.length(); for (int pos = start; pos < size; pos++) { final char c = text.charAt(pos); @@ -410,8 +398,8 @@ public class KeySpecParser { return size; } - public static String[] parseCsvString(String rawText, Resources res, int packageNameResId) { - final String text = resolveStringResource(rawText, res, packageNameResId); + public static String[] parseCsvString(String rawText, KeyboardLabelsSet labelsSet) { + final String text = resolveLabelReference(rawText, labelsSet); final int size = text.length(); if (size == 0) { return null; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java index 405b7ad05..8e0b21607 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java @@ -34,24 +34,55 @@ public class KeyStyles { private final HashMap<String, DeclaredKeyStyle> mStyles = new HashMap<String, DeclaredKeyStyle>(); - private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle(); - public interface KeyStyle { - public String[] getStringArray(TypedArray a, int index); - public String getString(TypedArray a, int index); - public int getInt(TypedArray a, int index, int defaultValue); - public int getFlag(TypedArray a, int index); + private final KeyboardLabelsSet mLabelsSet; + private final KeyStyle mEmptyKeyStyle; + + public KeyStyles(KeyboardLabelsSet labelsSet) { + mLabelsSet = labelsSet; + mEmptyKeyStyle = new EmptyKeyStyle(labelsSet); + } + + public static abstract class KeyStyle { + protected final KeyboardLabelsSet mLabelsSet; + + public KeyStyle(KeyboardLabelsSet labelsSet) { + mLabelsSet = labelsSet; + } + + public abstract String[] getStringArray(TypedArray a, int index); + public abstract String getString(TypedArray a, int index); + public abstract int getInt(TypedArray a, int index, int defaultValue); + public abstract int getFlag(TypedArray a, int index); + + protected String parseString(TypedArray a, int index) { + if (a.hasValue(index)) { + return KeySpecParser.resolveLabelReference(a.getString(index), mLabelsSet); + } + return null; + } + + protected String[] parseStringArray(TypedArray a, int index) { + if (a.hasValue(index)) { + return KeySpecParser.parseCsvString(a.getString(index), mLabelsSet); + } + return null; + } } - static class EmptyKeyStyle implements KeyStyle { + private static class EmptyKeyStyle extends KeyStyle { + public EmptyKeyStyle(KeyboardLabelsSet labelsSet) { + super(labelsSet); + } + @Override public String[] getStringArray(TypedArray a, int index) { - return KeyStyles.parseStringArray(a, index); + return parseStringArray(a, index); } @Override public String getString(TypedArray a, int index) { - return a.getString(index); + return parseString(a, index); } @Override @@ -65,9 +96,13 @@ public class KeyStyles { } } - static class DeclaredKeyStyle implements KeyStyle { + private static class DeclaredKeyStyle extends KeyStyle { private final HashMap<Integer, Object> mStyleAttributes = new HashMap<Integer, Object>(); + public DeclaredKeyStyle(KeyboardLabelsSet labelsSet) { + super(labelsSet); + } + @Override public String[] getStringArray(TypedArray a, int index) { if (a.hasValue(index)) { @@ -79,7 +114,7 @@ public class KeyStyles { @Override public String getString(TypedArray a, int index) { if (a.hasValue(index)) { - return a.getString(index); + return parseString(a, index); } return (String)mStyleAttributes.get(index); } @@ -120,7 +155,7 @@ public class KeyStyles { private void readString(TypedArray a, int index) { if (a.hasValue(index)) { - mStyleAttributes.put(index, a.getString(index)); + mStyleAttributes.put(index, parseString(a, index)); } } @@ -131,16 +166,15 @@ public class KeyStyles { } private void readFlag(TypedArray a, int index) { - final Integer value = (Integer)mStyleAttributes.get(index); if (a.hasValue(index)) { + final Integer value = (Integer)mStyleAttributes.get(index); mStyleAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0)); } } private void readStringArray(TypedArray a, int index) { - final String[] value = parseStringArray(a, index); - if (value != null) { - mStyleAttributes.put(index, value); + if (a.hasValue(index)) { + mStyleAttributes.put(index, parseStringArray(a, index)); } } @@ -149,14 +183,6 @@ public class KeyStyles { } } - static String[] parseStringArray(TypedArray a, int index) { - if (a.hasValue(index)) { - return KeySpecParser.parseCsvString( - a.getString(index), a.getResources(), R.string.english_ime_name); - } - return null; - } - public void parseKeyStyleAttributes(TypedArray keyStyleAttr, TypedArray keyAttrs, XmlPullParser parser) throws XmlPullParserException { final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName); @@ -169,7 +195,7 @@ public class KeyStyles { } } - final DeclaredKeyStyle style = new DeclaredKeyStyle(); + final DeclaredKeyStyle style = new DeclaredKeyStyle(mLabelsSet); if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) { final String parentStyle = keyStyleAttr.getString( R.styleable.Keyboard_KeyStyle_parentStyle); @@ -188,7 +214,7 @@ public class KeyStyles { return mStyles.get(styleName); } - public static KeyStyle getEmptyKeyStyle() { - return EMPTY_KEY_STYLE; + public KeyStyle getEmptyKeyStyle() { + return mEmptyKeyStyle; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java new file mode 100644 index 000000000..a46f3bf1b --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardLabelsSet.java @@ -0,0 +1,2477 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 com.android.inputmethod.keyboard.internal; + +import android.content.Context; +import android.content.res.Resources; + +import com.android.inputmethod.latin.R; + +import java.util.HashMap; + +/** + * !!!!! DO NOT EDIT THIS FILE !!!!! + * This file is generated by tools/makelabel. + */ +public final class KeyboardLabelsSet { + // Language to labels map. + private static final HashMap<String, String[]> sLocaleToLabelsMap = + new HashMap<String, String[]>(); + private static final HashMap<String, Integer> sNameToIdMap = new HashMap<String, Integer>(); + + private String[] mLabels; + // Resource name to label map. + private HashMap<String, String> mResourceNameToLabelsMap = new HashMap<String, String>(); + + public void setLanguage(final String language) { + mLabels = sLocaleToLabelsMap.get(language); + if (mLabels == null) { + mLabels = LANGUAGE_DEFAULT; + } + } + + public void loadStringResources(Context context) { + loadStringResourcesInternal(context, RESOURCE_NAMES, R.string.english_ime_name); + } + + /* package for test */ + void loadStringResourcesInternal(Context context, final String[] resourceNames, + int referenceId) { + final Resources res = context.getResources(); + final String packageName = res.getResourcePackageName(referenceId); + for (final String resName : resourceNames) { + final int resId = res.getIdentifier(resName, "string", packageName); + mResourceNameToLabelsMap.put(resName, res.getString(resId)); + } + } + + public String getLabel(final String name) { + if (mResourceNameToLabelsMap.containsKey(name)) { + return mResourceNameToLabelsMap.get(name); + } + final Integer id = sNameToIdMap.get(name); + if (id == null) throw new RuntimeException("Unknown label: " + name); + final String label = (id < mLabels.length) ? mLabels[id] : null; + return (label == null) ? LANGUAGE_DEFAULT[id] : label; + } + + private static final String[] RESOURCE_NAMES = { + // These labels' name should be aligned with the @string/<name> in values/strings.xml. + // Labels for action. + "label_go_key", + // "label_search_key", + "label_send_key", + "label_next_key", + "label_done_key", + "label_previous_key", + // Other labels. + "label_to_alpha_key", + "label_to_symbol_key", + "label_to_symbol_with_microphone_key", + "label_pause_key", + "label_wait_key", + }; + + private static final String[] NAMES = { + /* 0 */ "more_keys_for_a", + /* 1 */ "more_keys_for_e", + /* 2 */ "more_keys_for_i", + /* 3 */ "more_keys_for_o", + /* 4 */ "more_keys_for_u", + /* 5 */ "more_keys_for_s", + /* 6 */ "more_keys_for_n", + /* 7 */ "more_keys_for_c", + /* 8 */ "more_keys_for_y", + /* 9 */ "more_keys_for_d", + /* 10 */ "more_keys_for_r", + /* 11 */ "more_keys_for_t", + /* 12 */ "more_keys_for_z", + /* 13 */ "more_keys_for_k", + /* 14 */ "more_keys_for_l", + /* 15 */ "more_keys_for_g", + /* 16 */ "more_keys_for_v", + /* 17 */ "more_keys_for_h", + /* 18 */ "more_keys_for_j", + /* 19 */ "more_keys_for_w", + /* 20 */ "keylabel_for_nordic_row1_11", + /* 21 */ "keylabel_for_nordic_row2_10", + /* 22 */ "keylabel_for_nordic_row2_11", + /* 23 */ "more_keys_for_nordic_row2_10", + /* 24 */ "more_keys_for_nordic_row2_11", + /* 25 */ "keylabel_for_east_slavic_row1_9", + /* 26 */ "keylabel_for_east_slavic_row2_1", + /* 27 */ "keylabel_for_east_slavic_row3_5", + /* 28 */ "more_keys_for_cyrillic_u", + /* 29 */ "more_keys_for_cyrillic_ye", + /* 30 */ "more_keys_for_cyrillic_en", + /* 31 */ "more_keys_for_cyrillic_ha", + /* 32 */ "more_keys_for_east_slavic_row2_1", + /* 33 */ "more_keys_for_cyrillic_o", + /* 34 */ "more_keys_for_cyrillic_soft_sign", + /* 35 */ "keylabel_for_south_slavic_row1_6", + /* 36 */ "keylabel_for_south_slavic_row2_11", + /* 37 */ "keylabel_for_south_slavic_row3_1", + /* 38 */ "keylabel_for_south_slavic_row3_8", + /* 39 */ "more_keys_for_cyrillic_ie", + /* 40 */ "more_keys_for_cyrillic_i", + /* 41 */ "more_keys_for_single_quote", + /* 42 */ "more_keys_for_double_quote", + /* 43 */ "more_keys_for_tablet_double_quote", + /* 44 */ "more_keys_for_currency_dollar", + /* 45 */ "more_keys_for_currency_euro", + /* 46 */ "more_keys_for_currency_pound", + /* 47 */ "more_keys_for_currency_general", + /* 48 */ "more_keys_for_smiley", + /* 49 */ "more_keys_for_punctuation", + /* 50 */ "keyhintlabel_for_punctuation", + /* 51 */ "keylabel_for_popular_domain", + /* 52 */ "more_keys_for_popular_domain", + /* 53 */ "keylabel_for_symbols_1", + /* 54 */ "keylabel_for_symbols_2", + /* 55 */ "keylabel_for_symbols_3", + /* 56 */ "keylabel_for_symbols_4", + /* 57 */ "keylabel_for_symbols_5", + /* 58 */ "keylabel_for_symbols_6", + /* 59 */ "keylabel_for_symbols_7", + /* 60 */ "keylabel_for_symbols_8", + /* 61 */ "keylabel_for_symbols_9", + /* 62 */ "keylabel_for_symbols_0", + /* 63 */ "additional_more_keys_for_symbols_1", + /* 64 */ "additional_more_keys_for_symbols_2", + /* 65 */ "additional_more_keys_for_symbols_3", + /* 66 */ "additional_more_keys_for_symbols_4", + /* 67 */ "additional_more_keys_for_symbols_5", + /* 68 */ "additional_more_keys_for_symbols_6", + /* 69 */ "additional_more_keys_for_symbols_7", + /* 70 */ "additional_more_keys_for_symbols_8", + /* 71 */ "additional_more_keys_for_symbols_9", + /* 72 */ "additional_more_keys_for_symbols_0", + /* 73 */ "more_keys_for_symbols_1", + /* 74 */ "more_keys_for_symbols_2", + /* 75 */ "more_keys_for_symbols_3", + /* 76 */ "more_keys_for_symbols_4", + /* 77 */ "more_keys_for_symbols_5", + /* 78 */ "more_keys_for_symbols_6", + /* 79 */ "more_keys_for_symbols_7", + /* 80 */ "more_keys_for_symbols_8", + /* 81 */ "more_keys_for_symbols_9", + /* 82 */ "more_keys_for_symbols_0", + /* 83 */ "more_keys_for_am_pm", + /* 84 */ "settings_as_more_key", + /* 85 */ "keylabel_for_comma", + /* 86 */ "more_keys_for_comma", + /* 87 */ "action_next_as_more_key", + /* 88 */ "action_previous_as_more_key", + /* 89 */ "keylabel_for_symbols_question", + /* 90 */ "keylabel_for_symbols_semicolon", + /* 91 */ "keylabel_for_symbols_percent", + /* 92 */ "more_keys_for_symbols_question", + /* 93 */ "more_keys_for_symbols_semicolon", + /* 94 */ "more_keys_for_symbols_percent", + /* 95 */ "keylabel_for_tablet_comma", + /* 96 */ "keyhintlabel_for_tablet_comma", + /* 97 */ "more_keys_for_tablet_comma", + /* 98 */ "keyhintlabel_for_tablet_period", + /* 99 */ "more_keys_for_tablet_period", + /* 100 */ "keylabel_for_apostrophe", + /* 101 */ "keylabel_for_dash", + /* 102 */ "keyhintlabel_for_apostrophe", + /* 103 */ "keyhintlabel_for_dash", + /* 104 */ "more_keys_for_apostrophe", + /* 105 */ "more_keys_for_dash", + /* 106 */ "more_keys_for_bullet", + /* 107 */ "more_keys_for_star", + /* 108 */ "more_keys_for_plus", + /* 109 */ "more_keys_for_left_parenthesis", + /* 110 */ "more_keys_for_right_parenthesis", + /* 111 */ "more_keys_for_less_than", + /* 112 */ "more_keys_for_greater_than", + /* 113 */ "label_to_more_symbol_key", + /* 114 */ "label_to_more_symbol_for_tablet_key", + /* 115 */ "label_tab_key", + /* 116 */ "label_to_phone_numeric_key", + /* 117 */ "label_to_phone_symbols_key", + /* 118 */ "label_time_am", + /* 119 */ "label_time_pm", + }; + + private static final String EMPTY = ""; + + /* Default labels */ + private static final String[] LANGUAGE_DEFAULT = { + /* 0~ */ + EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, + EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, + EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, + EMPTY, EMPTY, + /* ~40 */ + /* 41 */ "!fixedColumnOrder!4,\u2018,\u2019,\u201A,\u201B", + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_double_quote">!fixedColumnOrder!6,“,”,„,‟,«,»</string> + /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB,\u00BB", + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«,»,‘,’,‚,‛</string> + /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B", + // U+00A2: "¢" CENT SIGN + // U+00A3: "£" POUND SIGN + // U+20AC: "€" EURO SIGN + // U+00A5: "¥" YEN SIGN + // U+20B1: "₱" PESO SIGN + /* 44 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1", + /* 45 */ "\u00A2,\u00A3,$,\u00A5,\u20B1", + /* 46 */ "\u00A2,$,\u20AC,\u00A5,\u20B1", + /* 47 */ "\u00A2,$,\u20AC,\u00A3,\u00A5,\u20B1", + /* 48 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ", + /* 49 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\\,,?,@,&,\\%,+,;,/,(,)", + /* 50 */ EMPTY, + /* 51 */ ".com", + // popular web domains for the locale - most popular, displayed on the keyboard + /* 52 */ "!hasLabels!,.net,.org,.gov,.edu", + /* 53 */ "1", + /* 54 */ "2", + /* 55 */ "3", + /* 56 */ "4", + /* 57 */ "5", + /* 58 */ "6", + /* 59 */ "7", + /* 60 */ "8", + /* 61 */ "9", + /* 62 */ "0", + /* 63~ */ + EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, + /* ~72 */ + // U+00B9: "¹" SUPERSCRIPT ONE + // U+00BD: "½" VULGAR FRACTION ONE HALF + // U+2153: "⅓" VULGAR FRACTION ONE THIRD + // U+00BC: "¼" VULGAR FRACTION ONE QUARTER + // U+215B: "⅛" VULGAR FRACTION ONE EIGHTH + /* 73 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B", + // U+00B2: "²" SUPERSCRIPT TWO + // U+2154: "⅔" VULGAR FRACTION TWO THIRDS + /* 74 */ "\u00B2,\u2154", + // U+00B3: "³" SUPERSCRIPT THREE + // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS + // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS + /* 75 */ "\u00B3,\u00BE,\u215C", + // U+2074: "⁴" SUPERSCRIPT FOUR + /* 76 */ "\u2074", + // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS + /* 77 */ "\u215D", + /* 78 */ EMPTY, + // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS + /* 79 */ "\u215E", + /* 80 */ EMPTY, + /* 81 */ EMPTY, + // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N + // U+2205: "∅" EMPTY SET + /* 82 */ "\u207F,\u2205", + /* 83 */ "!fixedColumnOrder!2,!hasLabels!,!label/label_time_am,!label/label_time_pm", + /* 84 */ "!icon/settingsKey|!code/key_settings", + /* 85 */ ",", + /* 86 */ EMPTY, + /* 87 */ "!hasLabels!,!label/label_next_key|!code/key_action_next", + /* 88 */ "!hasLabels!,!label/label_previous_key|!code/key_action_previous", + /* 89 */ "?", + /* 90 */ ";", + /* 91 */ "%", + // U+00BF: "¿" INVERTED QUESTION MARK + /* 92 */ "\u00BF", + /* 93 */ EMPTY, + // U+2030: "‰" PER MILLE SIGN + /* 94 */ "\u2030", + /* 95 */ ",", + /* 96 */ "!", + /* 97 */ "!", + /* 98 */ "?", + /* 99 */ "?", + /* 100 */ "\'", + /* 101 */ "-", + /* 102 */ "\"", + /* 103 */ "_", + /* 104 */ "\"", + /* 105 */ "_", + // U+266A: "♪" EIGHTH NOTE + // U+2665: "♥" BLACK HEART SUIT + // U+2660: "♠" BLACK SPADE SUIT + // U+2666: "♦" BLACK DIAMOND SUIT + // U+2663: "♣" BLACK CLUB SUIT + /* 106 */ "\u266A,\u2665,\u2660,\u2666,\u2663", + // U+2020: "†" DAGGER + // U+2021: "‡" DOUBLE DAGGER + // U+2605: "★" BLACK STAR + /* 107 */ "\u2020,\u2021,\u2605", + // U+00B1: "±" PLUS-MINUS SIGN + /* 108 */ "\u00B1", + // The all letters need to be mirrored are found at + // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt + /* 109 */ "!fixedColumnOrder!3,<,{,[", + /* 110 */ "!fixedColumnOrder!3,>,},]", + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + // U+2264: "≤" LESS-THAN OR EQUAL TO + // U+2265: "≥" GREATER-THAN EQUAL TO + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + // The following characters don't need BIDI mirroring. + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK + /* 111 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB", + /* 112 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB", + // Label for "switch to more symbol" modifier key. Must be short to fit on key! + /* 113 */ "= \\ <", + // Label for "switch to more symbol" modifier key on tablets. Must be short to fit on key! + /* 114 */ "~ \\ {", + // Label for "Tab" key. Must be short to fit on key! + /* 115 */ "Tab", + // Label for "switch to phone numeric" key. Must be short to fit on key! + /* 116 */ "123", + // Label for "switch to phone symbols" key. Must be short to fit on key! U+FF0A: "*" FULLWIDTH ASTERISK + // U+FF03: "#" FULLWIDTH NUMBER SIGN + /* 117 */ "\uFF0A\uFF03", + // Key label for "ante meridiem" + /* 118 */ "AM", + // Key label for "post meridiem" + /* 119 */ "PM", + }; + + /* Language ar: Arabic */ + private static final String[] LANGUAGE_ar = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + /* ~41 */ + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_double_quote">“,”,„,‟,«|»,»|«</string> + /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB", + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«|»,»|«;,‘,’,‚,‛</string> + /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B", + /* 44~ */ + null, null, null, null, null, + /* ~48 */ + // U+061F: "؟" ARABIC QUESTION MARK + // U+060C: "،" ARABIC COMMA + // U+061B: "؛" ARABIC SEMICOLON U+0650: "ِ" ARABIC KASRA + // U+064E: "َ" ARABIC FATHA + // U+064D: "ٍ" ARABIC KASRATAN + // U+064B: "ً" ARABIC FATHATAN + // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + // U+0655: "ٕ" ARABIC HAMZA BELOW + // U+0654: "ٔ" ARABIC HAMZA ABOVE U+064F: "ُ" ARABIC DAMMA + // U+064C: "ٌ" ARABIC DAMMATAN + // U+0651: "ّ" ARABIC SHADDA + // U+0652: "ْ" ARABIC SUKUN + // U+0653: "ٓ" ARABIC MADDAH ABOVE + // U+0640: "ـ" ARABIC TATWEEL In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. + /* 49 */ "!fixedColumnOrder!8,\",\',-,:,!,\u061F,\u060C,\u061B,\u0650,\u064E,\u064D,\u064B,\u0656,\u0670,\u0655,\u0654,\u064F,\u064C,\u0651,\u0652,\u0653,\u0640\u0640\u0640|\u0640,/", + /* 50 */ "\u064B", + /* 51 */ null, + /* 52 */ null, + // U+0661: "١" ARABIC-INDIC DIGIT ONE + /* 53 */ "\u0661", + // U+0662: "٢" ARABIC-INDIC DIGIT TWO + /* 54 */ "\u0662", + // U+0663: "٣" ARABIC-INDIC DIGIT THREE + /* 55 */ "\u0663", + // U+0664: "٤" ARABIC-INDIC DIGIT FOUR + /* 56 */ "\u0664", + // U+0665: "٥" ARABIC-INDIC DIGIT FIVE + /* 57 */ "\u0665", + // U+0666: "٦" ARABIC-INDIC DIGIT SIX + /* 58 */ "\u0666", + // U+0667: "٧" ARABIC-INDIC DIGIT SEVEN + /* 59 */ "\u0667", + // U+0668: "٨" ARABIC-INDIC DIGIT EIGHT + /* 60 */ "\u0668", + // U+0669: "٩" ARABIC-INDIC DIGIT NINE + /* 61 */ "\u0669", + // U+0660: "٠" ARABIC-INDIC DIGIT ZERO + /* 62 */ "\u0660", + /* 63 */ "1", + /* 64 */ "2", + /* 65 */ "3", + /* 66 */ "4", + /* 67 */ "5", + /* 68 */ "6", + /* 69 */ "7", + /* 70 */ "8", + /* 71 */ "9", + // U+066B: "٫" ARABIC DECIMAL SEPARATOR + // U+066C: "٬" ARABIC THOUSANDS SEPARATOR + /* 72 */ "0,\u066B,\u066C", + /* 73~ */ + null, null, null, null, null, null, null, null, null, null, null, null, + /* ~84 */ + // U+060C: "،" ARABIC COMMA + /* 85 */ "\u060C", + /* 86 */ "\\,", + /* 87 */ null, + /* 88 */ null, + /* 89 */ "\u061F", + /* 90 */ "\u061B", + // U+066A: "٪" ARABIC PERCENT SIGN + /* 91 */ "\u066A", + /* 92 */ "?", + /* 93 */ ";", + // U+2030: "‰" PER MILLE SIGN + /* 94 */ "%,\u2030", + /* 95~ */ + null, null, null, null, null, + /* ~99 */ + // U+060C: "،" ARABIC COMMA + // U+061B: "؛" ARABIC SEMICOLON + // U+061F: "؟" ARABIC QUESTION MARK + /* 100 */ "\u060C", + /* 101 */ ".", + /* 102 */ "\u061F", + /* 103 */ "\u064B", + /* 104 */ "\u061F,\u061B,!,:,-,/,\',\"", + // U+0651: "ّ" ARABIC SHADDA + // U+0652: "ْ" ARABIC SUKUN + // U+064C: "ٌ" ARABIC DAMMATAN + // U+0653: "ٓ" ARABIC MADDAH ABOVE + // U+064F: "ُ" ARABIC DAMMA U+0650: "ِ" ARABIC KASRA + // U+064E: "َ" ARABIC FATHA + // U+064B: "ً" ARABIC FATHATAN + // U+0640: "ـ" ARABIC TATWEEL + // U+064D: "ٍ" ARABIC KASRATAN U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + // U+0654: "ٔ" ARABIC HAMZA ABOVE + // U+0655: "ٕ" ARABIC HAMZA BELOW In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. + /* 105 */ "\u0651,\u0652,\u064C,\u0653,\u064F,\u0650,\u064E,\u064B,\u0640\u0640\u0640|\u0640,\u064D,\u0654,\u0656,\u0655,\u0670", + // U+266A: "♪" EIGHTH NOTE + /* 106 */ "\u266A", + // U+2605: "★" BLACK STAR + // U+066D: "٭" ARABIC FIVE POINTED STAR + /* 107 */ "\u2605,\u066D", + /* 108 */ null, + // The all letters need to be mirrored are found at + // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt U+FD3E: "﴾" ORNATE LEFT PARENTHESIS + // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS + /* 109 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]", + /* 110 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[", + // U+2264: "≤" LESS-THAN OR EQUAL TO + // U+2265: "≥" GREATER-THAN EQUAL TO + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + // The following characters don't need BIDI mirroring. + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK + /* 111 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB", + /* 112 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB", + }; + + /* Language be: Belarusian */ + private static final String[] LANGUAGE_be = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, + /* ~24 */ + // U+045E: "ў" CYRILLIC SMALL LETTER SHORT U + /* 25 */ "\u045E", + // U+044B: "ы" CYRILLIC SMALL LETTER YERU + /* 26 */ "\u044B", + // U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + /* 27 */ "\u0456", + /* 28~ */ + null, null, null, + /* ~30 */ + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 31 */ "\u044A", + /* 32 */ null, + /* 33 */ null, + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 34 */ "\u044A", + }; + + /* Language ca: Catalan */ + private static final String[] LANGUAGE_ca = { + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00AA: "ª" FEMININE ORDINAL INDICATOR + /* 0 */ "\u00E0,\u00E1,\u00E4,\u00E2,\u00E3,\u00E5,\u0105,\u00E6,\u0101,\u00AA", + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E8,\u00E9,\u00EB,\u00EA,\u0119,\u0117,\u0113", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B", + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+00BA: "º" MASCULINE ORDINAL INDICATOR + /* 3 */ "\u00F2,\u00F3,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B", + /* 5 */ null, + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u00F1,\u0144", + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + /* 7 */ "\u00E7,\u0107,\u010D", + /* 8~ */ + null, null, null, null, null, null, + /* ~13 */ + // U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + /* 14 */ "\u0140,\u0142", + }; + + /* Language cs: Czech */ + private static final String[] LANGUAGE_cs = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E1,\u00E0,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+011B: "ě" LATIN SMALL LETTER E WITH CARON + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E9,\u011B,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00ED,\u00EE,\u00EF,\u00EC,\u012F,\u012B", + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u016F,\u00FB,\u00FC,\u00F9,\u016B", + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + /* 5 */ "\u0161,\u00DF,\u015B", + // U+0148: "ň" LATIN SMALL LETTER N WITH CARON + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u0148,\u00F1,\u0144", + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + /* 7 */ "\u010D,\u00E7,\u0107", + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "\u00FD,\u00FF", + // U+010F: "ď" LATIN SMALL LETTER D WITH CARON + /* 9 */ "\u010F", + // U+0159: "ř" LATIN SMALL LETTER R WITH CARON + /* 10 */ "\u0159", + // U+0165: "ť" LATIN SMALL LETTER T WITH CARON + /* 11 */ "\u0165", + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + /* 12 */ "\u017E,\u017A,\u017C", + }; + + /* Language da: Danish */ + private static final String[] LANGUAGE_da = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E1,\u00E4,\u00E0,\u00E2,\u00E3,\u0101", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + /* 1 */ "\u00E9,\u00EB", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + /* 2 */ "\u00ED,\u00EF", + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F3,\u00F4,\u00F2,\u00F5,\u0153,\u014D", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B", + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + /* 5 */ "\u00DF,\u015B,\u0161", + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u00F1,\u0144", + /* 7 */ null, + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "\u00FD,\u00FF", + // U+00F0: "ð" LATIN SMALL LETTER ETH + /* 9 */ "\u00F0", + /* 10~ */ + null, null, null, null, + /* ~13 */ + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + /* 14 */ "\u0142", + /* 15~ */ + null, null, null, null, null, + /* ~19 */ + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + /* 20 */ "\u00E5", + // U+00E6: "æ" LATIN SMALL LETTER AE + /* 21 */ "\u00E6", + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 22 */ "\u00F8", + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + /* 23 */ "\u00E4", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + /* 24 */ "\u00F6", + }; + + /* Language de: German */ + private static final String[] LANGUAGE_de = { + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E4,\u00E2,\u00E0,\u00E1,\u00E6,\u00E3,\u00E5,\u0101", + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + /* 1 */ "\u0117", + /* 2 */ null, + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F6,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u00F8,\u014D", + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B", + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + /* 5 */ "\u00DF,\u015B,\u0161", + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u00F1,\u0144", + }; + + /* Language en: English */ + private static final String[] LANGUAGE_en = { + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E0,\u00E1,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101", + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0103", + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + /* 2 */ "\u00EE,\u00EF,\u00ED,\u012B,\u00EC", + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + /* 3 */ "\u00F4,\u00F6,\u00F2,\u00F3,\u0153,\u00F8\u014D,\u00F5", + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FB,\u00FC,\u00F9,\u00FA,\u016B", + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + /* 5 */ "\u00DF", + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + /* 6 */ "\u00F1", + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + /* 7 */ "\u00E7", + }; + + /* Language es: Spanish */ + private static final String[] LANGUAGE_es = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00AA: "ª" FEMININE ORDINAL INDICATOR + /* 0 */ "\u00E1,\u00E0,\u00E4,\u00E2,\u00E3,\u00E5,\u0105,\u00E6,\u0101,\u00AA", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E9,\u00E8,\u00EB,\u00EA,\u0119,\u0117,\u0113", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B", + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+00BA: "º" MASCULINE ORDINAL INDICATOR + /* 3 */ "\u00F3,\u00F2,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B", + /* 5 */ null, + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u00F1,\u0144", + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + /* 7 */ "\u00E7,\u0107,\u010D", + /* 8~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, + /* ~48 */ + // U+00A1: "¡" INVERTED EXCLAMATION MARK + // U+00BF: "¿" INVERTED QUESTION MARK + /* 49 */ "!fixedColumnOrder!7,#,-,\u00A1,!,\u00BF,\\,,?,\\%,+,;,:,/,(,),@,&,\",\'", + }; + + /* Language et: Estonian */ + private static final String[] LANGUAGE_et = { + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + /* 0 */ "\u00E4,\u0101,\u00E0,\u00E1,\u00E2,\u00E3,\u00E5,\u00E6,\u0105", + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+011B: "ě" LATIN SMALL LETTER E WITH CARON + /* 1 */ "\u0113,\u00E8,\u0117,\u00E9,\u00EA,\u00EB,\u0119,\u011B", + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+0131: "ı" LATIN SMALL LETTER DOTLESS I + /* 2 */ "\u012B,\u00EC,\u012F,\u00ED,\u00EE,\u00EF,\u0131", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 3 */ "\u00F6,\u00F5,\u00F2,\u00F3,\u00F4,\u0153,\u0151,\u00F8", + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + /* 4 */ "\u00FC,\u016B,\u0173,\u00F9,\u00FA,\u00FB,\u016F,\u0171", + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + /* 5 */ "\u0161,\u00DF,\u015B,\u015F", + // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u0146,\u00F1,\u0144,\u0144", + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + /* 7 */ "\u010D,\u00E7,\u0107", + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "\u00FD,\u00FF", + // U+010F: "ď" LATIN SMALL LETTER D WITH CARON + /* 9 */ "\u010F", + // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + // U+0159: "ř" LATIN SMALL LETTER R WITH CARON + // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE + /* 10 */ "\u0157,\u0159,\u0155", + // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + // U+0165: "ť" LATIN SMALL LETTER T WITH CARON + /* 11 */ "\u0163,\u0165", + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + /* 12 */ "\u017E,\u017C,\u017A", + // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA + /* 13 */ "\u0137", + // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON + /* 14 */ "\u013C,\u0142,\u013A,\u013E", + // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE + /* 15 */ "\u0123,\u011F", + /* 16~ */ + null, null, null, null, + /* ~19 */ + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + /* 20 */ "\u00FC", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + /* 21 */ "\u00F6", + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + /* 22 */ "\u00E4", + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + /* 23 */ "\u00F5", + }; + + /* Language fa: Persian */ + private static final String[] LANGUAGE_fa = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + /* ~41 */ + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_double_quote">“,”,„,‟,«|»,»|«</string> + /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB", + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«|»,»|«;,‘,’,‚,‛</string> + /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B", + /* 44~ */ + null, null, null, null, null, + /* ~48 */ + // U+061F: "؟" ARABIC QUESTION MARK + // U+060C: "،" ARABIC COMMA + // U+061B: "؛" ARABIC SEMICOLON U+0650: "ِ" ARABIC KASRA + // U+064E: "َ" ARABIC FATHA + // U+064D: "ٍ" ARABIC KASRATAN + // U+064B: "ً" ARABIC FATHATAN + // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + // U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + // U+0655: "ٕ" ARABIC HAMZA BELOW + // U+0654: "ٔ" ARABIC HAMZA ABOVE U+064F: "ُ" ARABIC DAMMA + // U+064C: "ٌ" ARABIC DAMMATAN + // U+0651: "ّ" ARABIC SHADDA + // U+0652: "ْ" ARABIC SUKUN + // U+0653: "ٓ" ARABIC MADDAH ABOVE + // U+0640: "ـ" ARABIC TATWEEL In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. + /* 49 */ "!fixedColumnOrder!8,\",\',-,:,!,\u061F,\u060C,\u061B,\u0650,\u064E,\u064D,\u064B,\u0656,\u0670,\u0655,\u0654,\u064F,\u064C,\u0651,\u0652,\u0653,\u0640\u0640\u0640|\u0640,/", + /* 50 */ "\u064B", + /* 51 */ null, + /* 52 */ null, + // U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE + /* 53 */ "\u06F1", + // U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO + /* 54 */ "\u06F2", + // U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE + /* 55 */ "\u06F3", + // U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR + /* 56 */ "\u06F4", + // U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE + /* 57 */ "\u06F5", + // U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX + /* 58 */ "\u06F6", + // U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN + /* 59 */ "\u06F7", + // U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT + /* 60 */ "\u06F8", + // U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE + /* 61 */ "\u06F9", + // U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO + /* 62 */ "\u06F0", + /* 63 */ "1", + /* 64 */ "2", + /* 65 */ "3", + /* 66 */ "4", + /* 67 */ "5", + /* 68 */ "6", + /* 69 */ "7", + /* 70 */ "8", + /* 71 */ "9", + // U+066B: "٫" ARABIC DECIMAL SEPARATOR + // U+066C: "٬" ARABIC THOUSANDS SEPARATOR + /* 72 */ "0,\u066B,\u066C", + /* 73~ */ + null, null, null, null, null, null, null, null, null, null, null, null, + /* ~84 */ + // U+060C: "،" ARABIC COMMA + /* 85 */ "\u060C", + /* 86 */ "\\,", + /* 87 */ null, + /* 88 */ null, + /* 89 */ "\u061F", + /* 90 */ "\u061B", + // U+066A: "٪" ARABIC PERCENT SIGN + /* 91 */ "\u066A", + /* 92 */ "?", + /* 93 */ ";", + // U+2030: "‰" PER MILLE SIGN + /* 94 */ "%,\u2030", + // U+060C: "،" ARABIC COMMA + // U+061B: "؛" ARABIC SEMICOLON + // U+061F: "؟" ARABIC QUESTION MARK + /* 95 */ "\u060C", + /* 96 */ "!", + /* 97 */ "!,\\,", + /* 98 */ "\u061F", + /* 99 */ "\u061F,?", + /* 100~ */ + null, null, null, + /* ~102 */ + /* 103 */ "\u064B", + /* 104 */ "\u061F,\u061B,!,:,-,/,\',\"", + // U+0651: "ّ" ARABIC SHADDA + // U+0652: "ْ" ARABIC SUKUN + // U+064C: "ٌ" ARABIC DAMMATAN + // U+0653: "ٓ" ARABIC MADDAH ABOVE + // U+064F: "ُ" ARABIC DAMMA U+0650: "ِ" ARABIC KASRA + // U+064E: "َ" ARABIC FATHA + // U+064B: "ً" ARABIC FATHATAN + // U+0640: "ـ" ARABIC TATWEEL + // U+064D: "ٍ" ARABIC KASRATAN U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + // U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + // U+0654: "ٔ" ARABIC HAMZA ABOVE + // U+0655: "ٕ" ARABIC HAMZA BELOW In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. + /* 105 */ "\u0651,\u0652,\u064C,\u0653,\u064F,\u0650,\u064E,\u064B,\u0640\u0640\u0640|\u0640,\u064D,\u0654,\u0656,\u0655,_,\u0670", + // U+266A: "♪" EIGHTH NOTE + /* 106 */ "\u266A", + // U+2605: "★" BLACK STAR + // U+066D: "٭" ARABIC FIVE POINTED STAR + /* 107 */ "\u2605,\u066D", + /* 108 */ null, + // The all letters need to be mirrored are found at + // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt U+FD3E: "﴾" ORNATE LEFT PARENTHESIS + // U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS + /* 109 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]", + /* 110 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[", + // U+2264: "≤" LESS-THAN OR EQUAL TO + // U+2265: "≥" GREATER-THAN EQUAL TO + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + // The following characters don't need BIDI mirroring. + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK + /* 111 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB", + /* 112 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB", + }; + + /* Language fi: Finnish */ + private static final String[] LANGUAGE_fi = { + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E6,\u00E0,\u00E1,\u00E2,\u00E3,\u0101", + /* 1 */ null, + /* 2 */ null, + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F8,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u014D", + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + /* 4 */ "\u00FC", + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + /* 5 */ "\u0161,\u00DF,\u015B", + /* 6~ */ + null, null, null, null, null, null, + /* ~11 */ + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + /* 12 */ "\u017E,\u017A,\u017C", + /* 13~ */ + null, null, null, null, null, null, null, + /* ~19 */ + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + /* 20 */ "\u00E5", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + /* 21 */ "\u00F6", + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + /* 22 */ "\u00E4", + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 23 */ "\u00F8", + // U+00E6: "æ" LATIN SMALL LETTER AE + /* 24 */ "\u00E6", + }; + + /* Language fr: French */ + private static final String[] LANGUAGE_fr = { + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00AA: "ª" FEMININE ORDINAL INDICATOR + /* 0 */ "\u00E0,\u00E2,%,\u00E6,\u00E1,\u00E4,\u00E3,\u00E5,\u0101,\u00AA", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,%,\u0119,\u0117,\u0113", + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00EE,%,\u00EF,\u00EC,\u00ED,\u012F,\u012B", + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+00BA: "º" MASCULINE ORDINAL INDICATOR + /* 3 */ "\u00F4,\u0153,%,\u00F6,\u00F2,\u00F3,\u00F5,\u00F8,\u014D,\u00BA", + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00F9,\u00FB,%,\u00FC,\u00FA,\u016B", + /* 5 */ null, + /* 6 */ null, + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + /* 7 */ "\u00E7,\u0107,\u010D", + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "%,\u00FF", + }; + + /* Language hi: Hindi */ + private static final String[] LANGUAGE_hi = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, + /* ~52 */ + // U+0967: "१" DEVANAGARI DIGIT ONE + /* 53 */ "\u0967", + // U+0968: "२" DEVANAGARI DIGIT TWO + /* 54 */ "\u0968", + // U+0969: "३" DEVANAGARI DIGIT THREE + /* 55 */ "\u0969", + // U+096A: "४" DEVANAGARI DIGIT FOUR + /* 56 */ "\u096A", + // U+096B: "५" DEVANAGARI DIGIT FIVE + /* 57 */ "\u096B", + // U+096C: "६" DEVANAGARI DIGIT SIX + /* 58 */ "\u096C", + // U+096D: "७" DEVANAGARI DIGIT SEVEN + /* 59 */ "\u096D", + // U+096E: "८" DEVANAGARI DIGIT EIGHT + /* 60 */ "\u096E", + // U+096F: "९" DEVANAGARI DIGIT NINE + /* 61 */ "\u096F", + // U+0966: "०" DEVANAGARI DIGIT ZERO + /* 62 */ "\u0966", + /* 63 */ "1", + /* 64 */ "2", + /* 65 */ "3", + /* 66 */ "4", + /* 67 */ "5", + /* 68 */ "6", + /* 69 */ "7", + /* 70 */ "8", + /* 71 */ "9", + /* 72 */ "0", + }; + + /* Language hr: Croatian */ + private static final String[] LANGUAGE_hr = { + /* 0~ */ + null, null, null, null, null, + /* ~4 */ + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + /* 5 */ "\u0161,\u015B,\u00DF", + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u00F1,\u0144", + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + /* 7 */ "\u010D,\u0107,\u00E7", + /* 8 */ null, + // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE + /* 9 */ "\u0111", + /* 10 */ null, + /* 11 */ null, + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + /* 12 */ "\u017E,\u017A,\u017C", + }; + + /* Language hu: Hungarian */ + private static final String[] LANGUAGE_hu = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E1,\u00E0,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00ED,\u00EE,\u00EF,\u00EC,\u012F,\u012B", + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F3,\u00F6,\u0151,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u00FC,\u0171,\u00FB,\u00F9,\u016B", + }; + + /* Language is: Icelandic */ + private static final String[] LANGUAGE_is = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E1,\u00E4,\u00E6,\u00E5,\u00E0,\u00E2,\u00E3,\u0101", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E9,\u00EB,\u00E8,\u00EA,\u0119,\u0117,\u0113", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00ED,\u00EF,\u00EE,\u00EC,\u012F,\u012B", + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B", + /* 5~ */ + null, null, null, + /* ~7 */ + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "\u00FD,\u00FF", + // U+00F0: "ð" LATIN SMALL LETTER ETH + /* 9 */ "\u00F0", + /* 10 */ null, + // U+00FE: "þ" LATIN SMALL LETTER THORN + /* 11 */ "\u00FE", + /* 12~ */ + null, null, null, null, null, null, null, null, + /* ~19 */ + // U+00F0: "ð" LATIN SMALL LETTER ETH + /* 20 */ "\u00F0", + // U+00E6: "æ" LATIN SMALL LETTER AE + /* 21 */ "\u00E6", + // U+00FE: "þ" LATIN SMALL LETTER THORN + /* 22 */ "\u00FE", + }; + + /* Language it: Italian */ + private static final String[] LANGUAGE_it = { + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00AA: "ª" FEMININE ORDINAL INDICATOR + /* 0 */ "\u00E0,\u00E1,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101,\u00AA", + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0119,\u0117,\u0113", + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00EC,\u00ED,\u00EE,\u00EF,\u012F,\u012B", + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+00BA: "º" MASCULINE ORDINAL INDICATOR + /* 3 */ "\u00F2,\u00F3,\u00F4,\u00F6,\u00F5,\u0153,\u00F8,\u014D,\u00BA", + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00F9,\u00FA,\u00FB,\u00FC,\u016B", + }; + + /* Language iw: Hebrew */ + private static final String[] LANGUAGE_iw = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + /* ~41 */ + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_double_quote">“,”,„,‟,«|»,»|«</string> + /* 42 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB", + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«|»,»|«;,‘,’,‚,‛</string> + /* 43 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B", + /* 44~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, + /* ~106 */ + // U+2605: "★" BLACK STAR + /* 107 */ "\u2605", + // U+00B1: "±" PLUS-MINUS SIGN + // U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN + /* 108 */ "\u00B1,\uFB29", + // The all letters need to be mirrored are found at + // http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt + /* 109 */ "!fixedColumnOrder!3,<|>,{|},[|]", + /* 110 */ "!fixedColumnOrder!3,>|<,}|{,]|[", + // U+2264: "≤" LESS-THAN OR EQUAL TO + // U+2265: "≥" GREATER-THAN EQUAL TO + // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + // The following characters don't need BIDI mirroring. + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK + /* 111 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB", + /* 112 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB", + }; + + /* Language ky: Kirghiz */ + private static final String[] LANGUAGE_ky = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, + /* ~24 */ + // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA + /* 25 */ "\u0449", + // U+044B: "ы" CYRILLIC SMALL LETTER YERU + /* 26 */ "\u044B", + // U+0438: "и" CYRILLIC SMALL LETTER I + /* 27 */ "\u0438", + // U+04AF: "ү" CYRILLIC SMALL LETTER STRAIGHT U + /* 28 */ "\u04AF", + /* 29 */ null, + // U+04A3: "ң" CYRILLIC SMALL LETTER EN WITH DESCENDER + /* 30 */ "\u04A3", + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 31 */ "\u044A", + /* 32 */ null, + // U+04E9: "ө" CYRILLIC SMALL LETTER BARRED O + /* 33 */ "\u04E9", + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 34 */ "\u044A", + }; + + /* Language lt: Lithuanian */ + private static final String[] LANGUAGE_lt = { + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+00E6: "æ" LATIN SMALL LETTER AE + /* 0 */ "\u0105,\u00E4,\u0101,\u00E0,\u00E1,\u00E2,\u00E3,\u00E5,\u00E6", + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+011B: "ě" LATIN SMALL LETTER E WITH CARON + /* 1 */ "\u0117,\u0119,\u0113,\u00E8,\u00E9,\u00EA,\u00EB,\u011B", + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+0131: "ı" LATIN SMALL LETTER DOTLESS I + /* 2 */ "\u012F,\u012B,\u00EC,\u00ED,\u00EE,\u00EF,\u0131", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 3 */ "\u00F6,\u00F5,\u00F2,\u00F3,\u00F4,\u0153,\u0151,\u00F8", + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + /* 4 */ "\u016B,\u0173,\u00FC,\u016B,\u00F9,\u00FA,\u00FB,\u016F,\u0171", + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + /* 5 */ "\u0161,\u00DF,\u015B,\u015F", + // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u0146,\u00F1,\u0144,\u0144", + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + /* 7 */ "\u010D,\u00E7,\u0107", + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "\u00FD,\u00FF", + // U+010F: "ď" LATIN SMALL LETTER D WITH CARON + /* 9 */ "\u010F", + // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + // U+0159: "ř" LATIN SMALL LETTER R WITH CARON + // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE + /* 10 */ "\u0157,\u0159,\u0155", + // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + // U+0165: "ť" LATIN SMALL LETTER T WITH CARON + /* 11 */ "\u0163,\u0165", + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + /* 12 */ "\u017E,\u017C,\u017A", + // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA + /* 13 */ "\u0137", + // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON + /* 14 */ "\u013C,\u0142,\u013A,\u013E", + // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE + /* 15 */ "\u0123,\u011F", + }; + + /* Language lv: Latvian */ + private static final String[] LANGUAGE_lv = { + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + /* 0 */ "\u0101,\u00E0,\u00E1,\u00E2,\u00E3,\u00E4,\u00E5,\u00E6,\u0105", + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+011B: "ě" LATIN SMALL LETTER E WITH CARON + /* 1 */ "\u0113,\u0117,\u00E8,\u00E9,\u00EA,\u00EB,\u0119,\u011B", + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+0131: "ı" LATIN SMALL LETTER DOTLESS I + /* 2 */ "\u012B,\u012F,\u00EC,\u00ED,\u00EE,\u00EF,\u0131", + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 3 */ "\u00F2,\u00F3,\u00F4,\u00F5,\u00F6,\u0153,\u0151,\u00F8", + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + /* 4 */ "\u016B,\u0173,\u00F9,\u00FA,\u00FB,\u00FC,\u016F,\u0171", + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + /* 5 */ "\u0161,\u00DF,\u015B,\u015F", + // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u0146,\u00F1,\u0144,\u0144", + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + /* 7 */ "\u010D,\u00E7,\u0107", + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "\u00FD,\u00FF", + // U+010F: "ď" LATIN SMALL LETTER D WITH CARON + /* 9 */ "\u010F", + // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + // U+0159: "ř" LATIN SMALL LETTER R WITH CARON + // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE + /* 10 */ "\u0157,\u0159,\u0155", + // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + // U+0165: "ť" LATIN SMALL LETTER T WITH CARON + /* 11 */ "\u0163,\u0165", + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + /* 12 */ "\u017E,\u017C,\u017A", + // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA + /* 13 */ "\u0137", + // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON + /* 14 */ "\u013C,\u0142,\u013A,\u013E", + // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE + /* 15 */ "\u0123,\u011F", + }; + + /* Language mk: Macedonian */ + private static final String[] LANGUAGE_mk = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, + /* ~34 */ + // U+0455: "ѕ" CYRILLIC SMALL LETTER DZE + /* 35 */ "\u0455", + // U+045C: "ќ" CYRILLIC SMALL LETTER KJE + /* 36 */ "\u045C", + // U+0437: "з" CYRILLIC SMALL LETTER ZE + /* 37 */ "\u0437", + // U+0453: "ѓ" CYRILLIC SMALL LETTER GJE + /* 38 */ "\u0453", + // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE + /* 39 */ "\u0450", + // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE + /* 40 */ "\u045D", + /* 41 */ null, + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_double_quote">!fixedColumnOrder!6,„,“,”,‟,«,»</string> + /* 42 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB", + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«,»,‘,’,‚,‛</string> + /* 43 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B", + }; + + /* Language nb: Norwegian Bokmål */ + private static final String[] LANGUAGE_nb = { + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E0,\u00E4,\u00E1,\u00E2,\u00E3,\u0101", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113", + /* 2 */ null, + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F4,\u00F2,\u00F3,\u00F6,\u00F5,\u0153,\u014D", + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B", + /* 5~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + /* ~19 */ + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + /* 20 */ "\u00E5", + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 21 */ "\u00F8", + // U+00E6: "æ" LATIN SMALL LETTER AE + /* 22 */ "\u00E6", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + /* 23 */ "\u00F6", + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + /* 24 */ "\u00E4", + }; + + /* Language nl: Dutch */ + private static final String[] LANGUAGE_nl = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E1,\u00E4,\u00E2,\u00E0,\u00E6,\u00E3,\u00E5,\u0101", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u00E9,\u00EB,\u00EA,\u00E8,\u0119,\u0117,\u0113", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+0133: "ij" LATIN SMALL LIGATURE IJ + /* 2 */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B,\u0133", + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B", + /* 5 */ null, + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u00F1,\u0144", + /* 7 */ null, + // U+0133: "ij" LATIN SMALL LIGATURE IJ + /* 8 */ "\u0133", + }; + + /* Language pl: Polish */ + private static final String[] LANGUAGE_pl = { + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u0105,\u00E1,\u00E0,\u00E2,\u00E4,\u00E6,\u00E3,\u00E5,\u0101", + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + /* 1 */ "\u0119,\u00E8,\u00E9,\u00EA,\u00EB,\u0117,\u0113", + /* 2 */ null, + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D", + /* 4 */ null, + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + /* 5 */ "\u015B,\u00DF,\u0161", + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + /* 6 */ "\u0144,\u00F1", + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + /* 7 */ "\u0107,\u00E7,\u010D", + /* 8~ */ + null, null, null, null, + /* ~11 */ + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + /* 12 */ "\u017C,\u017A,\u017E", + /* 13 */ null, + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + /* 14 */ "\u0142", + }; + + /* Language pt: Portuguese */ + private static final String[] LANGUAGE_pt = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00AA: "ª" FEMININE ORDINAL INDICATOR + /* 0 */ "\u00E1,\u00E3,\u00E0,\u00E2,\u00E4,\u00E5,\u00E6,\u00AA", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + /* 1 */ "\u00E9,\u00EA,\u00E8,\u0119,\u0117,\u0113,\u00EB", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00ED,\u00EE,\u00EC,\u00EF,\u012F,\u012B", + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+00BA: "º" MASCULINE ORDINAL INDICATOR + /* 3 */ "\u00F3,\u00F5,\u00F4,\u00F2,\u00F6,\u0153,\u00F8,\u014D,\u00BA", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B", + /* 5 */ null, + /* 6 */ null, + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + /* 7 */ "\u00E7,\u010D,\u0107", + }; + + /* Language rm: Raeto-Romance */ + private static final String[] LANGUAGE_rm = { + /* 0~ */ + null, null, null, + /* ~2 */ + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 3 */ "\u00F2,\u00F3,\u00F6,\u00F4,\u00F5,\u0153,\u00F8", + }; + + /* Language ro: Romanian */ + private static final String[] LANGUAGE_ro = { + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + /* 0 */ "\u00E2,\u00E3,\u0103,\u00E0,\u00E1,\u00E4,\u00E6,\u00E5,\u0101", + /* 1 */ null, + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B", + /* 3 */ null, + /* 4 */ null, + // U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + /* 5 */ "\u0219,\u00DF,\u015B,\u0161", + /* 6~ */ + null, null, null, null, null, + /* ~10 */ + // U+021B: "ț" LATIN SMALL LETTER T WITH COMMA BELOW + /* 11 */ "\u021B", + }; + + /* Language ru: Russian */ + private static final String[] LANGUAGE_ru = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, + /* ~24 */ + // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA + /* 25 */ "\u0449", + // U+044B: "ы" CYRILLIC SMALL LETTER YERU + /* 26 */ "\u044B", + // U+0438: "и" CYRILLIC SMALL LETTER I + /* 27 */ "\u0438", + /* 28 */ null, + // U+0451: "ё" CYRILLIC SMALL LETTER IO + /* 29 */ "\u0451", + /* 30 */ null, + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 31 */ "\u044A", + /* 32 */ null, + /* 33 */ null, + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 34 */ "\u044A", + }; + + /* Language sk: Slovak */ + private static final String[] LANGUAGE_sk = { + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + /* 0 */ "\u00E1,\u00E4,\u0101,\u00E0,\u00E2,\u00E3,\u00E5,\u00E6,\u0105", + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+011B: "ě" LATIN SMALL LETTER E WITH CARON + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + /* 1 */ "\u00E9,\u011B,\u0113,\u0117,\u00E8,\u00EA,\u00EB,\u0119", + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+0131: "ı" LATIN SMALL LETTER DOTLESS I + /* 2 */ "\u00ED,\u012B,\u012F,\u00EC,\u00EE,\u00EF,\u0131", + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 3 */ "\u00F4,\u00F3,\u00F6,\u00F2,\u00F5,\u0153,\u0151,\u00F8", + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + /* 4 */ "\u00FA,\u016F,\u00FC,\u016B,\u0173,\u00F9,\u00FB,\u0171", + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + /* 5 */ "\u0161,\u00DF,\u015B,\u015F", + // U+0148: "ň" LATIN SMALL LETTER N WITH CARON + // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + /* 6 */ "\u0148,\u0146,\u00F1,\u0144,\u0144", + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + /* 7 */ "\u010D,\u00E7,\u0107", + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + /* 8 */ "\u00FD,\u00FF", + // U+010F: "ď" LATIN SMALL LETTER D WITH CARON + /* 9 */ "\u010F", + // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE + // U+0159: "ř" LATIN SMALL LETTER R WITH CARON + // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + /* 10 */ "\u0155,\u0159,\u0157", + // U+0165: "ť" LATIN SMALL LETTER T WITH CARON + // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + /* 11 */ "\u0165,\u0163", + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + /* 12 */ "\u017E,\u017C,\u017A", + // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA + /* 13 */ "\u0137", + // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON + // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + /* 14 */ "\u013E,\u013A,\u013C,\u0142", + // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE + /* 15 */ "\u0123,\u011F", + }; + + /* Language sl: Slovenian */ + private static final String[] LANGUAGE_sl = { + /* 0~ */ + null, null, null, null, null, + /* ~4 */ + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + /* 5 */ "\u0161", + /* 6 */ null, + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + /* 7 */ "\u010D,\u0107", + /* 8 */ null, + // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE + /* 9 */ "\u0111", + /* 10 */ null, + /* 11 */ null, + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + /* 12 */ "\u017E", + }; + + /* Language sr: Serbian */ + private static final String[] LANGUAGE_sr = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, + /* ~34 */ + // U+0437: "з" CYRILLIC SMALL LETTER ZE + /* 35 */ "\u0437", + // U+045B: "ћ" CYRILLIC SMALL LETTER TSHE + /* 36 */ "\u045B", + // U+0455: "ѕ" CYRILLIC SMALL LETTER DZE + /* 37 */ "\u0455", + // U+0452: "ђ" CYRILLIC SMALL LETTER DJE + /* 38 */ "\u0452", + // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE + /* 39 */ "\u0450", + // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE + /* 40 */ "\u045D", + /* 41 */ null, + // U+2018: "‘" LEFT SINGLE QUOTATION MARK + // U+2019: "’" RIGHT SINGLE QUOTATION MARK + // U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + // U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + // U+201C: "“" LEFT DOUBLE QUOTATION MARK + // U+201D: "”" RIGHT DOUBLE QUOTATION MARK + // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + // U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_double_quote">!fixedColumnOrder!6,„,“,”,‟,«,»</string> + /* 42 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB", + // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«,»,‘,’,‚,‛</string> + /* 43 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B", + }; + + /* Language sv: Swedish */ + private static final String[] LANGUAGE_sv = { + /* 0 */ null, + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119", + /* 2 */ null, + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u0153,\u00F4,\u00F2,\u00F3,\u00F5,\u014D", + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B", + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + /* 5 */ "\u00DF,\u015B,\u0161", + /* 6~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, + /* ~19 */ + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + /* 20 */ "\u00E5", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + /* 21 */ "\u00F6", + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + /* 22 */ "\u00E4", + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + /* 23 */ "\u00F8", + // U+00E6: "æ" LATIN SMALL LETTER AE + /* 24 */ "\u00E6", + }; + + /* Language tr: Turkish */ + private static final String[] LANGUAGE_tr = { + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + /* 0 */ "\u00E2", + /* 1 */ null, + // U+0131: "ı" LATIN SMALL LETTER DOTLESS I + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + /* 2 */ "\u0131,\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B", + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + /* 3 */ "\u00F6,\u00F4,\u0153,\u00F2,\u00F3,\u00F5,\u00F8,\u014D", + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + /* 4 */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B", + // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + /* 5 */ "\u015F,\u00DF,\u015B,\u0161", + /* 6 */ null, + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + /* 7 */ "\u00E7,\u0107,\u010D", + /* 8~ */ + null, null, null, null, null, null, null, + /* ~14 */ + // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE + /* 15 */ "\u011F", + }; + + /* Language uk: Ukrainian */ + private static final String[] LANGUAGE_uk = { + /* 0~ */ + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, + /* ~24 */ + // U+0449: "щ" CYRILLIC SMALL LETTER SHCHA + /* 25 */ "\u0449", + // U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + /* 26 */ "\u0456", + // U+0438: "и" CYRILLIC SMALL LETTER I + /* 27 */ "\u0438", + /* 28~ */ + null, null, null, + /* ~30 */ + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 31 */ "\u044A", + // U+0457: "ї" CYRILLIC SMALL LETTER YI + /* 32 */ "\u0457", + /* 33 */ null, + // U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN + /* 34 */ "\u044A", + }; + + /* Language vi: Vietnamese */ + private static final String[] LANGUAGE_vi = { + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+1EA3: "ả" LATIN SMALL LETTER A WITH HOOK ABOVE + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+1EA1: "ạ" LATIN SMALL LETTER A WITH DOT BELOW + // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE + // U+1EB1: "ằ" LATIN SMALL LETTER A WITH BREVE AND GRAVE + // U+1EAF: "ắ" LATIN SMALL LETTER A WITH BREVE AND ACUTE + // U+1EB3: "ẳ" LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE + // U+1EB5: "ẵ" LATIN SMALL LETTER A WITH BREVE AND TILDE + // U+1EB7: "ặ" LATIN SMALL LETTER A WITH BREVE AND DOT BELOW + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+1EA7: "ầ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE + // U+1EA5: "ấ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE + // U+1EA9: "ẩ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE + // U+1EAB: "ẫ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE + // U+1EAD: "ậ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW + /* 0 */ "\u00E0,\u00E1,\u1EA3,\u00E3,\u1EA1,\u0103,\u1EB1,\u1EAF,\u1EB3,\u1EB5,\u1EB7,\u00E2,\u1EA7,\u1EA5,\u1EA9,\u1EAB,\u1EAD", + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+1EBB: "ẻ" LATIN SMALL LETTER E WITH HOOK ABOVE + // U+1EBD: "ẽ" LATIN SMALL LETTER E WITH TILDE + // U+1EB9: "ẹ" LATIN SMALL LETTER E WITH DOT BELOW + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+1EC1: "ề" LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE + // U+1EBF: "ế" LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE + // U+1EC3: "ể" LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE + // U+1EC5: "ễ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE + // U+1EC7: "ệ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW + /* 1 */ "\u00E8,\u00E9,\u1EBB,\u1EBD,\u1EB9,\u00EA,\u1EC1,\u1EBF,\u1EC3,\u1EC5,\u1EC7", + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+1EC9: "ỉ" LATIN SMALL LETTER I WITH HOOK ABOVE + // U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE + // U+1ECB: "ị" LATIN SMALL LETTER I WITH DOT BELOW + /* 2 */ "\u00EC,\u00ED,\u1EC9,\u0129,\u1ECB", + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+1ECF: "ỏ" LATIN SMALL LETTER O WITH HOOK ABOVE + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+1ECD: "ọ" LATIN SMALL LETTER O WITH DOT BELOW + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+1ED3: "ồ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE + // U+1ED1: "ố" LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE + // U+1ED5: "ổ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE + // U+1ED7: "ỗ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE + // U+1ED9: "ộ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW + // U+01A1: "ơ" LATIN SMALL LETTER O WITH HORN + // U+1EDD: "ờ" LATIN SMALL LETTER O WITH HORN AND GRAVE + // U+1EDB: "ớ" LATIN SMALL LETTER O WITH HORN AND ACUTE + // U+1EDF: "ở" LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE + // U+1EE1: "ỡ" LATIN SMALL LETTER O WITH HORN AND TILDE + // U+1EE3: "ợ" LATIN SMALL LETTER O WITH HORN AND DOT BELOW + /* 3 */ "\u00F2,\u00F3,\u1ECF,\u00F5,\u1ECD,\u00F4,\u1ED3,\u1ED1,\u1ED5,\u1ED7,\u1ED9,\u01A1,\u1EDD,\u1EDB,\u1EDF,\u1EE1,\u1EE3", + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+1EE7: "ủ" LATIN SMALL LETTER U WITH HOOK ABOVE + // U+0169: "ũ" LATIN SMALL LETTER U WITH TILDE + // U+1EE5: "ụ" LATIN SMALL LETTER U WITH DOT BELOW + // U+01B0: "ư" LATIN SMALL LETTER U WITH HORN + // U+1EEB: "ừ" LATIN SMALL LETTER U WITH HORN AND GRAVE + // U+1EE9: "ứ" LATIN SMALL LETTER U WITH HORN AND ACUTE + // U+1EED: "ử" LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE + // U+1EEF: "ữ" LATIN SMALL LETTER U WITH HORN AND TILDE + // U+1EF1: "ự" LATIN SMALL LETTER U WITH HORN AND DOT BELOW + /* 4 */ "\u00F9,\u00FA,\u1EE7,\u0169,\u1EE5,\u01B0,\u1EEB,\u1EE9,\u1EED,\u1EEF,\u1EF1", + /* 5~ */ + null, null, null, + /* ~7 */ + // U+1EF3: "ỳ" LATIN SMALL LETTER Y WITH GRAVE + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+1EF7: "ỷ" LATIN SMALL LETTER Y WITH HOOK ABOVE + // U+1EF9: "ỹ" LATIN SMALL LETTER Y WITH TILDE + // U+1EF5: "ỵ" LATIN SMALL LETTER Y WITH DOT BELOW + /* 8 */ "\u1EF3,\u00FD,\u1EF7,\u1EF9,\u1EF5", + // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE + /* 9 */ "\u0111", + }; + + /* Language zz: No language */ + private static final String[] LANGUAGE_zz = { + // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + // U+00E6: "æ" LATIN SMALL LETTER AE + // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE + // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + // U+00AA: "ª" FEMININE ORDINAL INDICATOR + /* 0 */ "\u00E0,\u00E1,\u00E2,\u00E3,\u00E4,\u00E5,\u00E6,\u00E3,\u00E5,\u0101,\u0103,\u0105,\u00AA", + // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + // U+0115: "ĕ" LATIN SMALL LETTER E WITH BREVE + // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + // U+011B: "ě" LATIN SMALL LETTER E WITH CARON + /* 1 */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113,\u0115,\u0117,\u0119,\u011B", + // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + // U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE + // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + // U+012D: "ĭ" LATIN SMALL LETTER I WITH BREVE + // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + // U+0131: "ı" LATIN SMALL LETTER DOTLESS I + // U+0133: "ij" LATIN SMALL LIGATURE IJ + /* 2 */ "\u00EC,\u00ED,\u00EE,\u00EF,\u0129,\u012B,\u012D,\u012F,\u0131,\u0133", + // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + // U+014F: "ŏ" LATIN SMALL LETTER O WITH BREVE + // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + // U+0153: "œ" LATIN SMALL LIGATURE OE + // U+00BA: "º" MASCULINE ORDINAL INDICATOR + /* 3 */ "\u00F2,\u00F3,\u00F4,\u00F5,\u00F6,\u00F8,\u014D,\u014F,\u0151,\u0153,\u00BA", + // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + // U+0169: "ũ" LATIN SMALL LETTER U WITH TILDE + // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + // U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE + // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + /* 4 */ "\u00F9,\u00FA,\u00FB,\u00FC,\u0169,\u016B,\u016D,\u016F,\u0171,\u0173", + // U+00DF: "ß" LATIN SMALL LETTER SHARP S + // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + // U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX + // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + // U+0161: "š" LATIN SMALL LETTER S WITH CARON + // U+017F: "ſ" LATIN SMALL LETTER LONG S + /* 5 */ "\u00DF,\u015B,\u015D,\u015F,\u0161,\u017F", + // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + // U+0148: "ň" LATIN SMALL LETTER N WITH CARON + // U+0149: "ʼn" LATIN SMALL LETTER N PRECEDED BY APOSTROPHE + // U+014B: "ŋ" LATIN SMALL LETTER ENG + /* 6 */ "\u00F1,\u0144,\u0146,\u0148,\u0149,\u014B", + // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + // U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX + // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE + // U+010D: "č" LATIN SMALL LETTER C WITH CARON + /* 7 */ "\u00E7,\u0107,\u0109,\u010B,\u010D", + // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX + // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + // U+0133: "ij" LATIN SMALL LIGATURE IJ + /* 8 */ "\u00FD,\u0177,\u00FF,\u0133", + // U+010F: "ď" LATIN SMALL LETTER D WITH CARON + // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE + // U+00F0: "ð" LATIN SMALL LETTER ETH + /* 9 */ "\u010F,\u0111,\u00F0", + // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE + // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + // U+0159: "ř" LATIN SMALL LETTER R WITH CARON + /* 10 */ "\u0155,\u0157,\u0159", + // U+00FE: "þ" LATIN SMALL LETTER THORN + // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + // U+0165: "ť" LATIN SMALL LETTER T WITH CARON + // U+0167: "ŧ" LATIN SMALL LETTER T WITH STROKE + /* 11 */ "\u00FE,\u0163,\u0165,\u0167", + // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + /* 12 */ "\u017A,\u017C,\u017E", + // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA + // U+0138: "ĸ" LATIN SMALL LETTER KRA + /* 13 */ "\u0137,\u0138", + // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON + // U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT + // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + /* 14 */ "\u013A,\u013C,\u013E,\u0140,\u0142", + // U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX + // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE + // U+0121: "ġ" LATIN SMALL LETTER G WITH DOT ABOVE + // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + /* 15 */ "\u011D,\u011F,\u0121,\u0123", + /* 16 */ null, + // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX + /* 17 */ "\u0125", + // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX + /* 18 */ "\u0135", + // U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX + /* 19 */ "\u0175", + }; + + private static final Object[] LANGUAGES_AND_LABELS = { + "DEFAULT", LANGUAGE_DEFAULT, /* default */ + "ar", LANGUAGE_ar, /* Arabic */ + "be", LANGUAGE_be, /* Belarusian */ + "ca", LANGUAGE_ca, /* Catalan */ + "cs", LANGUAGE_cs, /* Czech */ + "da", LANGUAGE_da, /* Danish */ + "de", LANGUAGE_de, /* German */ + "en", LANGUAGE_en, /* English */ + "es", LANGUAGE_es, /* Spanish */ + "et", LANGUAGE_et, /* Estonian */ + "fa", LANGUAGE_fa, /* Persian */ + "fi", LANGUAGE_fi, /* Finnish */ + "fr", LANGUAGE_fr, /* French */ + "hi", LANGUAGE_hi, /* Hindi */ + "hr", LANGUAGE_hr, /* Croatian */ + "hu", LANGUAGE_hu, /* Hungarian */ + "is", LANGUAGE_is, /* Icelandic */ + "it", LANGUAGE_it, /* Italian */ + "iw", LANGUAGE_iw, /* Hebrew */ + "ky", LANGUAGE_ky, /* Kirghiz */ + "lt", LANGUAGE_lt, /* Lithuanian */ + "lv", LANGUAGE_lv, /* Latvian */ + "mk", LANGUAGE_mk, /* Macedonian */ + "nb", LANGUAGE_nb, /* Norwegian Bokmål */ + "nl", LANGUAGE_nl, /* Dutch */ + "pl", LANGUAGE_pl, /* Polish */ + "pt", LANGUAGE_pt, /* Portuguese */ + "rm", LANGUAGE_rm, /* Raeto-Romance */ + "ro", LANGUAGE_ro, /* Romanian */ + "ru", LANGUAGE_ru, /* Russian */ + "sk", LANGUAGE_sk, /* Slovak */ + "sl", LANGUAGE_sl, /* Slovenian */ + "sr", LANGUAGE_sr, /* Serbian */ + "sv", LANGUAGE_sv, /* Swedish */ + "tr", LANGUAGE_tr, /* Turkish */ + "uk", LANGUAGE_uk, /* Ukrainian */ + "vi", LANGUAGE_vi, /* Vietnamese */ + "zz", LANGUAGE_zz, /* No language */ + }; + + static { + int id = 0; + for (final String name : NAMES) { + sNameToIdMap.put(name, id++); + } + + for (int i = 0; i < LANGUAGES_AND_LABELS.length; i += 2) { + final String language = (String)LANGUAGES_AND_LABELS[i]; + final String[] labels = (String[])LANGUAGES_AND_LABELS[i + 1]; + sLocaleToLabelsMap.put(language, labels); + } + } +} diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index cc7540e4e..2d958e17d 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -17,11 +17,8 @@ package com.android.inputmethod.latin; import android.content.Context; -import android.content.res.AssetFileDescriptor; -import android.content.res.Resources; import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.LocaleUtils.RunInLocale; import java.util.Arrays; import java.util.Locale; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index e4d839690..b0c2adc79 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -20,11 +20,8 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetFileDescriptor; -import android.content.res.Resources; import android.util.Log; -import com.android.inputmethod.latin.LocaleUtils.RunInLocale; - import java.io.File; import java.util.ArrayList; import java.util.Locale; @@ -155,14 +152,8 @@ class BinaryDictionaryGetter { * Returns a file address from a resource, or null if it cannot be opened. */ private static AssetFileAddress loadFallbackResource(final Context context, - final int fallbackResId, final Locale locale) { - final RunInLocale<AssetFileDescriptor> job = new RunInLocale<AssetFileDescriptor>() { - @Override - protected AssetFileDescriptor job(Resources res) { - return res.openRawResourceFd(fallbackResId); - } - }; - final AssetFileDescriptor afd = job.runInLocale(context.getResources(), locale); + final int fallbackResId) { + final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId); if (afd == null) { Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId=" + fallbackResId); @@ -264,13 +255,13 @@ class BinaryDictionaryGetter { * - Uses a content provider to get a public dictionary set, as per the protocol described * in BinaryDictionaryFileDumper. * If that fails: - * - Gets a file name from the fallback resource passed as an argument. + * - Gets a file name from the built-in dictionary for this locale, if any. * If that fails: * - Returns null. * @return The list of addresses of valid dictionary files, or null. */ public static ArrayList<AssetFileAddress> getDictionaryFiles(final Locale locale, - final Context context, final int fallbackResId) { + final Context context) { // cacheWordListsFromContentProvider returns the list of files it copied to local // storage, but we don't really care about what was copied NOW: what we want is the @@ -299,8 +290,9 @@ class BinaryDictionaryGetter { } if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) { - final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId, - locale); + final int fallbackResId = + DictionaryFactory.getMainDictionaryResourceId(context.getResources(), locale); + final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId); if (null != fallbackAsset) { fileList.add(fallbackAsset); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index fedb45407..bf05f3bc3 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -21,8 +21,6 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.util.Log; -import com.android.inputmethod.latin.LocaleUtils.RunInLocale; - import java.io.File; import java.util.ArrayList; import java.util.LinkedList; @@ -38,24 +36,22 @@ public class DictionaryFactory { * Initializes a dictionary from a dictionary pack, with explicit flags. * * This searches for a content provider providing a dictionary pack for the specified - * locale. If none is found, it falls back to using the resource passed as fallBackResId - * as a dictionary. + * locale. If none is found, it falls back to the built-in dictionary - if any. * @param context application context for reading resources * @param locale the locale for which to create the dictionary - * @param fallbackResId the id of the resource to use as a fallback if no pack is found * @param useFullEditDistance whether to use the full edit distance in suggestions * @return an initialized instance of DictionaryCollection */ public static DictionaryCollection createDictionaryFromManager(final Context context, - final Locale locale, final int fallbackResId, final boolean useFullEditDistance) { + final Locale locale, final boolean useFullEditDistance) { if (null == locale) { Log.e(TAG, "No locale defined for dictionary"); - return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale)); + return new DictionaryCollection(createBinaryDictionary(context, locale)); } final LinkedList<Dictionary> dictList = new LinkedList<Dictionary>(); final ArrayList<AssetFileAddress> assetFileList = - BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId); + BinaryDictionaryGetter.getDictionaryFiles(locale, context); if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { final BinaryDictionary binaryDictionary = @@ -77,17 +73,14 @@ public class DictionaryFactory { * Initializes a dictionary from a dictionary pack, with default flags. * * This searches for a content provider providing a dictionary pack for the specified - * locale. If none is found, it falls back to using the resource passed as fallBackResId - * as a dictionary. + * locale. If none is found, it falls back to the built-in dictionary, if any. * @param context application context for reading resources * @param locale the locale for which to create the dictionary - * @param fallbackResId the id of the resource to use as a fallback if no pack is found * @return an initialized instance of DictionaryCollection */ public static DictionaryCollection createDictionaryFromManager(final Context context, - final Locale locale, final int fallbackResId) { - return createDictionaryFromManager(context, locale, fallbackResId, - false /* useFullEditDistance */); + final Locale locale) { + return createDictionaryFromManager(context, locale, false /* useFullEditDistance */); } /** @@ -98,16 +91,11 @@ public class DictionaryFactory { * @return an initialized instance of BinaryDictionary */ protected static BinaryDictionary createBinaryDictionary(final Context context, - final int resId, final Locale locale) { + final Locale locale) { AssetFileDescriptor afd = null; try { - final RunInLocale<AssetFileDescriptor> job = new RunInLocale<AssetFileDescriptor>() { - @Override - protected AssetFileDescriptor job(Resources res) { - return res.openRawResourceFd(resId); - } - }; - afd = job.runInLocale(context.getResources(), locale); + final int resId = getMainDictionaryResourceId(context.getResources(), locale); + afd = context.getResources().openRawResourceFd(resId); if (afd == null) { Log.e(TAG, "Found the resource but it is compressed. resId=" + resId); return null; @@ -123,7 +111,7 @@ public class DictionaryFactory { return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(), false /* useFullEditDistance */, locale); } catch (android.content.res.Resources.NotFoundException e) { - Log.e(TAG, "Could not find the resource. resId=" + resId); + Log.e(TAG, "Could not find the resource"); return null; } finally { if (null != afd) { @@ -163,41 +151,31 @@ public class DictionaryFactory { * @return whether a (non-placeholder) dictionary is available or not. */ public static boolean isDictionaryAvailable(Context context, Locale locale) { - final RunInLocale<Boolean> job = new RunInLocale<Boolean>() { - @Override - protected Boolean job(Resources res) { - final int resourceId = getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final boolean hasDictionary = isFullDictionary(afd); - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - /* Um, what can we do here exactly? */ - } - return hasDictionary; - } - }; - return job.runInLocale(context.getResources(), locale); + final Resources res = context.getResources(); + final int resourceId = getMainDictionaryResourceId(res, locale); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final boolean hasDictionary = isFullDictionary(afd); + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + /* Um, what can we do here exactly? */ + } + return hasDictionary; } // TODO: Do not use the size of the dictionary as an unique dictionary ID. public static Long getDictionaryId(final Context context, final Locale locale) { - final RunInLocale<Long> job = new RunInLocale<Long>() { - @Override - protected Long job(Resources res) { - final int resourceId = getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) - ? afd.getLength() - : null; - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - } - return size; - } - }; - return job.runInLocale(context.getResources(), locale); + final Resources res = context.getResources(); + final int resourceId = getMainDictionaryResourceId(res, locale); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) + ? afd.getLength() + : null; + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + } + return size; } // TODO: Find the Right Way to find out whether the resource is a placeholder or not. @@ -214,13 +192,32 @@ public class DictionaryFactory { return (afd != null && afd.getLength() > PLACEHOLDER_LENGTH); } + private static final String DEFAULT_MAIN_DICT = "main"; + private static final String MAIN_DICT_PREFIX = "main_"; + /** * Returns a main dictionary resource id + * @param locale dictionary locale * @return main dictionary resource id */ - public static int getMainDictionaryResourceId(Resources res) { - final String MAIN_DIC_NAME = "main"; - String packageName = LatinIME.class.getPackage().getName(); - return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); + public static int getMainDictionaryResourceId(Resources res, Locale locale) { + final String packageName = LatinIME.class.getPackage().getName(); + int resId; + + // Try to find main_language_country dictionary. + if (!locale.getCountry().isEmpty()) { + final String dictLanguageCountry = MAIN_DICT_PREFIX + locale.toString().toLowerCase(); + if ((resId = res.getIdentifier(dictLanguageCountry, "raw", packageName)) != 0) { + return resId; + } + } + + // Try to find main_language dictionary. + final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage(); + if ((resId = res.getIdentifier(dictLanguage, "raw", packageName)) != 0) { + return resId; + } + + return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", packageName); } } diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java new file mode 100644 index 000000000..53e8b74de --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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 com.android.inputmethod.latin; + +import android.content.Context; +import android.os.SystemClock; +import android.util.Log; + +import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.makedict.BinaryDictInputOutput; +import com.android.inputmethod.latin.makedict.FusionDictionary; +import com.android.inputmethod.latin.makedict.FusionDictionary.Node; +import com.android.inputmethod.latin.makedict.UnsupportedFormatException; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Abstract base class for an expandable dictionary that can be created and updated dynamically + * during runtime. When updated it automatically generates a new binary dictionary to handle future + * queries in native code. This binary dictionary is written to internal storage, and potentially + * shared across multiple ExpandableBinaryDictionary instances. Updates to each dictionary filename + * are controlled across multiple instances to ensure that only one instance can update the same + * dictionary at the same time. + */ +abstract public class ExpandableBinaryDictionary extends Dictionary { + + /** Used for Log actions from this class */ + private static final String TAG = ExpandableBinaryDictionary.class.getSimpleName(); + + /** Whether to print debug output to log */ + private static boolean DEBUG = false; + + /** + * The maximum length of a word in this dictionary. This is the same value as the binary + * dictionary. + */ + protected static final int MAX_WORD_LENGTH = BinaryDictionary.MAX_WORD_LENGTH; + + /** + * A static map of locks, each of which controls access to a single binary dictionary file. They + * ensure that only one instance can update the same dictionary at the same time. The key for + * this map is the filename and the value is the shared dictionary controller associated with + * that filename. + */ + private static final HashMap<String, DictionaryController> sSharedDictionaryControllers = + new HashMap<String, DictionaryController>(); + + /** The application context. */ + protected final Context mContext; + + /** + * The binary dictionary generated dynamically from the fusion dictionary. This is used to + * answer unigram and bigram queries. + */ + private BinaryDictionary mBinaryDictionary; + + /** The expandable fusion dictionary used to generate the binary dictionary. */ + private FusionDictionary mFusionDictionary; + + /** The dictionary type id. */ + public final int mDicTypeId; + + /** + * The name of this dictionary, used as the filename for storing the binary dictionary. Multiple + * dictionary instances with the same filename is supported, with access controlled by + * DictionaryController. + */ + private final String mFilename; + + /** Controls access to the shared binary dictionary file across multiple instances. */ + private final DictionaryController mSharedDictionaryController; + + /** Controls access to the local binary dictionary for this instance. */ + private final DictionaryController mLocalDictionaryController = new DictionaryController(); + + /** + * Abstract method for loading the unigrams and bigrams of a given dictionary in a background + * thread. + */ + protected abstract void loadDictionaryAsync(); + + /** + * Gets the shared dictionary controller for the given filename. + */ + private static synchronized DictionaryController getSharedDictionaryController( + String filename) { + DictionaryController controller = sSharedDictionaryControllers.get(filename); + if (controller == null) { + controller = new DictionaryController(); + sSharedDictionaryControllers.put(filename, controller); + } + return controller; + } + + /** + * Creates a new expandable binary dictionary. + * + * @param context The application context of the parent. + * @param filename The filename for this binary dictionary. Multiple dictionaries with the same + * filename is supported. + * @param dictType The type of this dictionary. + */ + public ExpandableBinaryDictionary( + final Context context, final String filename, final int dictType) { + mDicTypeId = dictType; + mFilename = filename; + mContext = context; + mBinaryDictionary = null; + mSharedDictionaryController = getSharedDictionaryController(filename); + clearFusionDictionary(); + } + + /** + * Closes and cleans up the binary dictionary. + */ + @Override + public void close() { + // Ensure that no other threads are accessing the local binary dictionary. + mLocalDictionaryController.lock(); + try { + if (mBinaryDictionary != null) { + mBinaryDictionary.close(); + mBinaryDictionary = null; + } + } finally { + mLocalDictionaryController.unlock(); + } + } + + /** + * Clears the fusion dictionary on the Java side. Note: Does not modify the binary dictionary on + * the native side. + */ + public void clearFusionDictionary() { + mFusionDictionary = new FusionDictionary(new Node(), new FusionDictionary.DictionaryOptions( + new HashMap<String, String>(), false, false)); + } + + /** + * Adds a word unigram to the fusion dictionary. Call updateBinaryDictionary when all changes + * are done to update the binary dictionary. + */ + // TODO: Create "cache dictionary" to cache fresh words for frequently updated dictionaries, + // considering performance regression. + protected void addWord(final String word, final int frequency) { + mFusionDictionary.add(word, frequency, null, null); + } + + /** + * Sets a word bigram in the fusion dictionary. Call updateBinaryDictionary when all changes are + * done to update the binary dictionary. + */ + // TODO: Create "cache dictionary" to cache fresh bigrams for frequently updated dictionaries, + // considering performance regression. + protected void setBigram(final String prevWord, final String word, final int frequency) { + mFusionDictionary.setBigram(prevWord, word, frequency); + } + + @Override + public void getWords(final WordComposer codes, final WordCallback callback, + final ProximityInfo proximityInfo) { + asyncReloadDictionaryIfRequired(); + getWordsInner(codes, callback, proximityInfo); + } + + protected final void getWordsInner(final WordComposer codes, final WordCallback callback, + final ProximityInfo proximityInfo) { + // Ensure that there are no concurrent calls to getWords. If there are, do nothing and + // return. + if (mLocalDictionaryController.tryLock()) { + try { + if (mBinaryDictionary != null) { + mBinaryDictionary.getWords(codes, callback, proximityInfo); + } + } finally { + mLocalDictionaryController.unlock(); + } + } + } + + @Override + public void getBigrams(final WordComposer codes, final CharSequence previousWord, + final WordCallback callback) { + asyncReloadDictionaryIfRequired(); + getBigramsInner(codes, previousWord, callback); + } + + protected void getBigramsInner(final WordComposer codes, final CharSequence previousWord, + final WordCallback callback) { + if (mLocalDictionaryController.tryLock()) { + try { + if (mBinaryDictionary != null) { + mBinaryDictionary.getBigrams(codes, previousWord, callback); + } + } finally { + mLocalDictionaryController.unlock(); + } + } + } + + @Override + public boolean isValidWord(final CharSequence word) { + asyncReloadDictionaryIfRequired(); + return isValidWordInner(word); + } + + protected boolean isValidWordInner(final CharSequence word) { + if (mLocalDictionaryController.tryLock()) { + try { + if (mBinaryDictionary != null) { + return mBinaryDictionary.isValidWord(word); + } + } finally { + mLocalDictionaryController.unlock(); + } + } + return false; + } + + /** + * Load the current binary dictionary from internal storage in a background thread. If no binary + * dictionary exists, this method will generate one. + */ + protected void loadDictionary() { + mLocalDictionaryController.mLastUpdateRequestTime = SystemClock.uptimeMillis(); + asyncReloadDictionaryIfRequired(); + } + + /** + * Loads the current binary dictionary from internal storage. Assumes the dictionary file + * exists. + */ + protected void loadBinaryDictionary() { + if (DEBUG) { + Log.d(TAG, "Loading binary dictionary: request=" + + mSharedDictionaryController.mLastUpdateRequestTime + " update=" + + mSharedDictionaryController.mLastUpdateTime); + } + + final File file = new File(mContext.getFilesDir(), mFilename); + final String filename = file.getAbsolutePath(); + final long length = file.length(); + + // Build the new binary dictionary + final BinaryDictionary newBinaryDictionary = + new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */, + null); + + if (mBinaryDictionary != null) { + // Ensure all threads accessing the current dictionary have finished before swapping in + // the new one. + final BinaryDictionary oldBinaryDictionary = mBinaryDictionary; + mLocalDictionaryController.lock(); + mBinaryDictionary = newBinaryDictionary; + mLocalDictionaryController.unlock(); + oldBinaryDictionary.close(); + } else { + mBinaryDictionary = newBinaryDictionary; + } + } + + /** + * Generates and writes a new binary dictionary based on the contents of the fusion dictionary. + */ + private void generateBinaryDictionary() { + if (DEBUG) { + Log.d(TAG, "Generating binary dictionary: request=" + + mSharedDictionaryController.mLastUpdateRequestTime + " update=" + + mSharedDictionaryController.mLastUpdateTime); + } + + loadDictionaryAsync(); + + final File file = new File(mContext.getFilesDir(), mFilename); + FileOutputStream out = null; + try { + out = new FileOutputStream(file); + BinaryDictInputOutput.writeDictionaryBinary(out, mFusionDictionary, 1); + out.flush(); + out.close(); + clearFusionDictionary(); + } catch (IOException e) { + Log.e(TAG, "IO exception while writing file: " + e); + } catch (UnsupportedFormatException e) { + Log.e(TAG, "Unsupported format: " + e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + /** + * Sets whether or not the dictionary is out of date and requires a reload. + */ + protected void setRequiresReload(final boolean reload) { + final long time = reload ? SystemClock.uptimeMillis() : 0; + mSharedDictionaryController.mLastUpdateRequestTime = time; + mLocalDictionaryController.mLastUpdateRequestTime = time; + if (DEBUG) { + Log.d(TAG, "Reload request: request=" + time + " update=" + + mSharedDictionaryController.mLastUpdateTime); + } + } + + /** + * Reloads the dictionary if required. Reload will occur asynchronously in a separate thread. + */ + void asyncReloadDictionaryIfRequired() { + new AsyncReloadDictionaryTask().start(); + } + + /** + * Reloads the dictionary if required. Access is controlled on a per dictionary file basis and + * supports concurrent calls from multiple instances that share the same dictionary file. + */ + protected final void syncReloadDictionaryIfRequired() { + if (mBinaryDictionary != null && !mLocalDictionaryController.isOutOfDate()) { + return; + } + + // Ensure that only one thread attempts to read or write to the shared binary dictionary + // file at the same time. + mSharedDictionaryController.lock(); + try { + final long time = SystemClock.uptimeMillis(); + if (mSharedDictionaryController.isOutOfDate() || !dictionaryFileExists()) { + // If the shared dictionary file does not exist or is out of date, the first + // instance that acquires the lock will generate a new one. + mSharedDictionaryController.mLastUpdateTime = time; + mLocalDictionaryController.mLastUpdateTime = time; + generateBinaryDictionary(); + loadBinaryDictionary(); + } else if (mLocalDictionaryController.isOutOfDate()) { + // Otherwise, if only the local dictionary for this instance is out of date, load + // the shared dictionary from file. + mLocalDictionaryController.mLastUpdateTime = time; + loadBinaryDictionary(); + } + } finally { + mSharedDictionaryController.unlock(); + } + } + + private boolean dictionaryFileExists() { + final File file = new File(mContext.getFilesDir(), mFilename); + return file.exists(); + } + + /** + * Thread class for asynchronously reloading and rewriting the binary dictionary. + */ + private class AsyncReloadDictionaryTask extends Thread { + @Override + public void run() { + syncReloadDictionaryIfRequired(); + } + } + + /** + * Lock for controlling access to a given binary dictionary and for tracking whether the + * dictionary is out of date. Can be shared across multiple dictionary instances that access the + * same filename. + */ + private static class DictionaryController extends ReentrantLock { + private volatile long mLastUpdateTime = 0; + private volatile long mLastUpdateRequestTime = 0; + + private boolean isOutOfDate() { + return (mLastUpdateRequestTime > mLastUpdateTime); + } + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e0fa2f838..7cdeef897 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -493,37 +493,28 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); - final Context context = this; - final RunInLocale<Void> job = new RunInLocale<Void>() { - @Override - protected Void job(Resources res) { - final ContactsDictionary oldContactsDictionary; - if (mSuggest != null) { - oldContactsDictionary = mSuggest.getContactsDictionary(); - mSuggest.close(); - } else { - oldContactsDictionary = null; - } + final ContactsDictionary oldContactsDictionary; + if (mSuggest != null) { + oldContactsDictionary = mSuggest.getContactsDictionary(); + mSuggest.close(); + } else { + oldContactsDictionary = null; + } - int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); - mSuggest = new Suggest(context, mainDicResId, keyboardLocale); - if (mSettingsValues.mAutoCorrectEnabled) { - mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); - } + mSuggest = new Suggest(this, keyboardLocale); + if (mSettingsValues.mAutoCorrectEnabled) { + mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); + } - mUserDictionary = new UserDictionary(context, localeStr); - mSuggest.setUserDictionary(mUserDictionary); - mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); + mUserDictionary = new UserDictionary(this, localeStr); + mSuggest.setUserDictionary(mUserDictionary); + mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); - resetContactsDictionary(oldContactsDictionary); + resetContactsDictionary(oldContactsDictionary); - mUserHistoryDictionary - = new UserHistoryDictionary(context, localeStr, Suggest.DIC_USER_HISTORY); - mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); - return null; - } - }; - job.runInLocale(mResources, keyboardLocale); + mUserHistoryDictionary = new UserHistoryDictionary( + this, localeStr, Suggest.DIC_USER_HISTORY); + mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); } /** @@ -559,9 +550,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } /* package private */ void resetSuggestMainDict() { - final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); - int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(mResources); - mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); + mSuggest.resetMainDict(this, mSubtypeSwitcher.getInputLocale()); } @Override diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 49ab7f9d7..526acf128 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -97,7 +97,7 @@ public class SettingsValues { } } final String[] suggestPuncsSpec = KeySpecParser.parseCsvString( - res.getString(R.string.suggested_punctuations), res, R.string.english_ime_name); + res.getString(R.string.suggested_punctuations), null); mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec); mSymbolsExcludedFromWordSeparators = res.getString(R.string.symbols_excluded_from_word_separators); diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index fa6664b1a..c3f3bd598 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -104,8 +104,8 @@ public class Suggest implements Dictionary.WordCallback { private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; - public Suggest(final Context context, final int dictionaryResId, final Locale locale) { - initAsynchronously(context, dictionaryResId, locale); + public Suggest(final Context context, final Locale locale) { + initAsynchronously(context, locale); } /* package for test */ Suggest(final Context context, final File dictionary, @@ -119,9 +119,8 @@ public class Suggest implements Dictionary.WordCallback { addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary); } - private void initAsynchronously(final Context context, final int dictionaryResId, - final Locale locale) { - resetMainDict(context, dictionaryResId, locale); + private void initAsynchronously(final Context context, final Locale locale) { + resetMainDict(context, locale); // TODO: read the whitelist and init the pool asynchronously too. // initPool should be done asynchronously now that the pool is thread-safe. @@ -146,14 +145,13 @@ public class Suggest implements Dictionary.WordCallback { } } - public void resetMainDict(final Context context, final int dictionaryResId, - final Locale locale) { + public void resetMainDict(final Context context, final Locale locale) { mMainDict = null; new Thread("InitializeBinaryDictionary") { @Override public void run() { final Dictionary newMainDict = DictionaryFactory.createDictionaryFromManager( - context, locale, dictionaryResId); + context, locale); mMainDict = newMainDict; addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict); addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict); diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index 7bb307662..bb3ba8651 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -38,6 +38,7 @@ public class WhitelistDictionary extends ExpandableDictionary { // TODO: Conform to the async load contact of ExpandableDictionary public WhitelistDictionary(final Context context, final Locale locale) { super(context, Suggest.DIC_WHITELIST); + // TODO: Move whitelist dictionary into main dictionary. final RunInLocale<Void> job = new RunInLocale<Void>() { @Override protected Void job(Resources res) { diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 97296147f..576fbe696 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -386,10 +386,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService final int script = getScriptFromLocale(locale); final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo( SpellCheckerProximityInfo.getProximityForScript(script)); - final Resources resources = getResources(); - final int fallbackResourceId = DictionaryFactory.getMainDictionaryResourceId(resources); final DictionaryCollection dictionaryCollection = - DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId, + DictionaryFactory.createDictionaryFromManager(this, locale, true /* useFullEditDistance */); final String localeStr = locale.toString(); Dictionary userDictionary = mUserDictionaries.get(localeStr); |