Loading java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +47 −45 Original line number Original line Diff line number Diff line Loading @@ -25,49 +25,42 @@ import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import java.util.HashMap; import java.util.Locale; import java.util.Locale; // TODO: Make this an immutable class. public final class KeyboardTextsSet { public final class KeyboardTextsSet { public static final String PREFIX_TEXT = "!text/"; public static final String PREFIX_TEXT = "!text/"; private static final String PREFIX_RESOURCE = "!string/"; public static final String SWITCH_TO_ALPHA_KEY_LABEL = "keylabel_to_alpha"; public static final String SWITCH_TO_ALPHA_KEY_LABEL = "keylabel_to_alpha"; private static final char BACKSLASH = Constants.CODE_BACKSLASH; private static final char BACKSLASH = Constants.CODE_BACKSLASH; private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; private static final int MAX_REFERENCE_INDIRECTION = 10; private Resources mResources; private Locale mResourceLocale; private String mResourcePackageName; private String[] mTextsTable; private String[] mTextsTable; // Resource name to text map. private HashMap<String, String> mResourceNameToTextsMap = new HashMap<>(); public void setLocale(final Locale locale, final Context context) { public void setLocale(final Locale locale, final Context context) { mTextsTable = KeyboardTextsTable.getTextsTable(locale); final Resources res = context.getResources(); final Resources res = context.getResources(); final int referenceId = context.getApplicationInfo().labelRes; final String resourcePackageName = res.getResourcePackageName(referenceId); final RunInLocale<Void> job = new RunInLocale<Void>() { @Override protected Void job(final Resources resource) { loadStringResourcesInternal(res, RESOURCE_NAMES, resourcePackageName); return null; } }; // Null means the current system locale. // Null means the current system locale. job.runInLocale(res, final String resourcePackageName = res.getResourcePackageName( SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale); context.getApplicationInfo().labelRes); setLocale(locale, res, resourcePackageName); } } @UsedForTesting @UsedForTesting void loadStringResourcesInternal(final Resources res, final String[] resourceNames, public void setLocale(final Locale locale, final Resources res, final String resourcePackageName) { final String resourcePackageName) { for (final String resName : resourceNames) { mResources = res; final int resId = res.getIdentifier(resName, "string", resourcePackageName); // Null means the current system locale. mResourceNameToTextsMap.put(resName, res.getString(resId)); mResourceLocale = SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale; } mResourcePackageName = resourcePackageName; mTextsTable = KeyboardTextsTable.getTextsTable(locale); } } public String getText(final String name) { public String getText(final String name) { final String text = mResourceNameToTextsMap.get(name); return KeyboardTextsTable.getText(name, mTextsTable); return (text != null) ? text : KeyboardTextsTable.getText(name, mTextsTable); } } private static int searchTextNameEnd(final String text, final int start) { private static int searchTextNameEnd(final String text, final int start) { Loading @@ -93,13 +86,14 @@ public final class KeyboardTextsSet { StringBuilder sb; StringBuilder sb; do { do { level++; level++; if (level >= MAX_STRING_REFERENCE_INDIRECTION) { if (level >= MAX_REFERENCE_INDIRECTION) { throw new RuntimeException("Too many " + PREFIX_TEXT + "name indirection: " + text); throw new RuntimeException("Too many " + PREFIX_TEXT + " or " + PREFIX_RESOURCE + " reference indirection: " + text); } } final int prefixLen = PREFIX_TEXT.length(); final int prefixLength = PREFIX_TEXT.length(); final int size = text.length(); final int size = text.length(); if (size < prefixLen) { if (size < prefixLength) { break; break; } } Loading @@ -110,10 +104,12 @@ public final class KeyboardTextsSet { if (sb == null) { if (sb == null) { sb = new StringBuilder(text.substring(0, pos)); sb = new StringBuilder(text.substring(0, pos)); } } final int end = searchTextNameEnd(text, pos + prefixLen); pos = expandReference(text, pos, PREFIX_TEXT, sb); final String name = text.substring(pos + prefixLen, end); } else if (text.startsWith(PREFIX_RESOURCE, pos)) { sb.append(getText(name)); if (sb == null) { pos = end - 1; sb = new StringBuilder(text.substring(0, pos)); } pos = expandReference(text, pos, PREFIX_RESOURCE, sb); } else if (c == BACKSLASH) { } else if (c == BACKSLASH) { if (sb != null) { if (sb != null) { // Append both escape character and escaped character. // Append both escape character and escaped character. Loading @@ -132,18 +128,24 @@ public final class KeyboardTextsSet { return TextUtils.isEmpty(text) ? null : text; return TextUtils.isEmpty(text) ? null : text; } } // These texts' name should be aligned with the @string/<name> in private int expandReference(final String text, final int pos, final String prefix, // values*/strings-action-keys.xml. final StringBuilder sb) { static final String[] RESOURCE_NAMES = { final int prefixLength = prefix.length(); // Labels for action. final int end = searchTextNameEnd(text, pos + prefixLength); "label_go_key", final String name = text.substring(pos + prefixLength, end); "label_send_key", if (prefix.equals(PREFIX_TEXT)) { "label_next_key", sb.append(getText(name)); "label_done_key", } else { // PREFIX_RESOURCE "label_search_key", final String resourcePackageName = mResourcePackageName; "label_previous_key", final RunInLocale<String> getTextJob = new RunInLocale<String>() { // Other labels. @Override "label_pause_key", protected String job(final Resources res) { "label_wait_key", final int resId = res.getIdentifier(name, "string", resourcePackageName); return res.getString(resId); } }; }; sb.append(getTextJob.runInLocale(mResources, mResourceLocale)); } return end - 1; } } } java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java +78 −44 Original line number Original line Diff line number Diff line Loading @@ -209,48 +209,56 @@ public final class KeyboardTextsTable { /* 123: 1 */ "morekeys_less_than", /* 123: 1 */ "morekeys_less_than", /* 124: 1 */ "morekeys_greater_than", /* 124: 1 */ "morekeys_greater_than", /* 125: 1 */ "morekeys_exclamation", /* 125: 1 */ "morekeys_exclamation", /* 126: 0 */ "morekeys_currency_generic", /* 126: 1 */ "label_go_key", /* 127: 0 */ "morekeys_symbols_1", /* 127: 1 */ "label_send_key", /* 128: 0 */ "morekeys_symbols_2", /* 128: 1 */ "label_next_key", /* 129: 0 */ "morekeys_symbols_3", /* 129: 1 */ "label_done_key", /* 130: 0 */ "morekeys_symbols_4", /* 130: 1 */ "label_search_key", /* 131: 0 */ "morekeys_symbols_5", /* 131: 1 */ "label_previous_key", /* 132: 0 */ "morekeys_symbols_6", /* 132: 1 */ "label_pause_key", /* 133: 0 */ "morekeys_symbols_7", /* 133: 1 */ "label_wait_key", /* 134: 0 */ "morekeys_symbols_8", /* 134: 0 */ "morekeys_currency_generic", /* 135: 0 */ "morekeys_symbols_9", /* 135: 0 */ "morekeys_symbols_1", /* 136: 0 */ "morekeys_symbols_0", /* 136: 0 */ "morekeys_symbols_2", /* 137: 0 */ "morekeys_am_pm", /* 137: 0 */ "morekeys_symbols_3", /* 138: 0 */ "keyspec_settings", /* 138: 0 */ "morekeys_symbols_4", /* 139: 0 */ "keyspec_shortcut", /* 139: 0 */ "morekeys_symbols_5", /* 140: 0 */ "keyspec_action_next", /* 140: 0 */ "morekeys_symbols_6", /* 141: 0 */ "keyspec_action_previous", /* 141: 0 */ "morekeys_symbols_7", /* 142: 0 */ "keylabel_to_more_symbol", /* 142: 0 */ "morekeys_symbols_8", /* 143: 0 */ "keylabel_tablet_to_more_symbol", /* 143: 0 */ "morekeys_symbols_9", /* 144: 0 */ "keylabel_to_phone_numeric", /* 144: 0 */ "morekeys_symbols_0", /* 145: 0 */ "keylabel_to_phone_symbols", /* 145: 0 */ "morekeys_am_pm", /* 146: 0 */ "keylabel_time_am", /* 146: 0 */ "keyspec_settings", /* 147: 0 */ "keylabel_time_pm", /* 147: 0 */ "keyspec_shortcut", /* 148: 0 */ "keyspec_popular_domain", /* 148: 0 */ "keyspec_action_next", /* 149: 0 */ "morekeys_popular_domain", /* 149: 0 */ "keyspec_action_previous", /* 150: 0 */ "keyspecs_left_parenthesis_more_keys", /* 150: 0 */ "keylabel_to_more_symbol", /* 151: 0 */ "keyspecs_right_parenthesis_more_keys", /* 151: 0 */ "keylabel_tablet_to_more_symbol", /* 152: 0 */ "single_laqm_raqm", /* 152: 0 */ "keylabel_to_phone_numeric", /* 153: 0 */ "single_raqm_laqm", /* 153: 0 */ "keylabel_to_phone_symbols", /* 154: 0 */ "double_laqm_raqm", /* 154: 0 */ "keylabel_time_am", /* 155: 0 */ "double_raqm_laqm", /* 155: 0 */ "keylabel_time_pm", /* 156: 0 */ "single_lqm_rqm", /* 156: 0 */ "keyspec_popular_domain", /* 157: 0 */ "single_9qm_lqm", /* 157: 0 */ "morekeys_popular_domain", /* 158: 0 */ "single_9qm_rqm", /* 158: 0 */ "keyspecs_left_parenthesis_more_keys", /* 159: 0 */ "single_rqm_9qm", /* 159: 0 */ "keyspecs_right_parenthesis_more_keys", /* 160: 0 */ "double_lqm_rqm", /* 160: 0 */ "single_laqm_raqm", /* 161: 0 */ "double_9qm_lqm", /* 161: 0 */ "single_raqm_laqm", /* 162: 0 */ "double_9qm_rqm", /* 162: 0 */ "double_laqm_raqm", /* 163: 0 */ "double_rqm_9qm", /* 163: 0 */ "double_raqm_laqm", /* 164: 0 */ "morekeys_single_quote", /* 164: 0 */ "single_lqm_rqm", /* 165: 0 */ "morekeys_double_quote", /* 165: 0 */ "single_9qm_lqm", /* 166: 0 */ "morekeys_tablet_double_quote", /* 166: 0 */ "single_9qm_rqm", /* 167: 0 */ "keyspec_emoji_action_key", /* 167: 0 */ "single_rqm_9qm", /* 168: 0 */ "double_lqm_rqm", /* 169: 0 */ "double_9qm_lqm", /* 170: 0 */ "double_9qm_rqm", /* 171: 0 */ "double_rqm_9qm", /* 172: 0 */ "morekeys_single_quote", /* 173: 0 */ "morekeys_double_quote", /* 174: 0 */ "morekeys_tablet_double_quote", /* 175: 0 */ "keyspec_emoji_action_key", }; }; private static final String EMPTY = ""; private static final String EMPTY = ""; Loading Loading @@ -379,6 +387,14 @@ public final class KeyboardTextsTable { /* morekeys_greater_than */ "!fixedColumnOrder!3,!text/keyspec_right_single_angle_quote,!text/keyspec_greater_than_equal,!text/keyspec_right_double_angle_quote", /* morekeys_greater_than */ "!fixedColumnOrder!3,!text/keyspec_right_single_angle_quote,!text/keyspec_greater_than_equal,!text/keyspec_right_double_angle_quote", // U+00A1: "¡" INVERTED EXCLAMATION MARK // U+00A1: "¡" INVERTED EXCLAMATION MARK /* morekeys_exclamation */ "\u00A1", /* morekeys_exclamation */ "\u00A1", /* label_go_key */ "!string/label_go_key", /* label_send_key */ "!string/label_send_key", /* label_next_key */ "!string/label_next_key", /* label_done_key */ "!string/label_done_key", /* label_search_key */ "!string/label_search_key", /* label_previous_key */ "!string/label_previous_key", /* label_pause_key */ "!string/label_pause_key", /* label_wait_key */ "!string/label_wait_key", /* morekeys_currency_generic */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1", /* morekeys_currency_generic */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1", // U+00B9: "¹" SUPERSCRIPT ONE // U+00B9: "¹" SUPERSCRIPT ONE // U+00BD: "½" VULGAR FRACTION ONE HALF // U+00BD: "½" VULGAR FRACTION ONE HALF Loading Loading @@ -1885,6 +1901,24 @@ public final class KeyboardTextsTable { /* ~ morekeys_s */ /* ~ morekeys_s */ // U+20B9: "₹" INDIAN RUPEE SIGN // U+20B9: "₹" INDIAN RUPEE SIGN /* keyspec_currency */ "\u20B9", /* keyspec_currency */ "\u20B9", /* morekeys_y ~ */ 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, 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, /* ~ morekeys_exclamation */ /* label_go_key */ "Go", /* label_send_key */ "Send", /* label_next_key */ "Next", /* label_done_key */ "Done", /* label_search_key */ "Search", /* label_previous_key */ "Prev", /* label_pause_key */ "Pause", /* label_wait_key */ "Wait", }; }; /* Locale hr: Croatian */ /* Locale hr: Croatian */ Loading Loading @@ -3952,7 +3986,7 @@ public final class KeyboardTextsTable { private static final Object[] LOCALES_AND_TEXTS = { private static final Object[] LOCALES_AND_TEXTS = { // "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */ // "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */ "DEFAULT", TEXTS_DEFAULT, /* 168/168 DEFAULT */ "DEFAULT", TEXTS_DEFAULT, /* 176/176 DEFAULT */ "af" , TEXTS_af, /* 7/ 13 Afrikaans */ "af" , TEXTS_af, /* 7/ 13 Afrikaans */ "ar" , TEXTS_ar, /* 55/110 Arabic */ "ar" , TEXTS_ar, /* 55/110 Arabic */ "az_AZ" , TEXTS_az_AZ, /* 11/ 18 Azerbaijani (Azerbaijan) */ "az_AZ" , TEXTS_az_AZ, /* 11/ 18 Azerbaijani (Azerbaijan) */ Loading @@ -3974,7 +4008,7 @@ public final class KeyboardTextsTable { "fr" , TEXTS_fr, /* 13/ 62 French */ "fr" , TEXTS_fr, /* 13/ 62 French */ "gl_ES" , TEXTS_gl_ES, /* 7/ 8 Gallegan (Spain) */ "gl_ES" , TEXTS_gl_ES, /* 7/ 8 Gallegan (Spain) */ "hi" , TEXTS_hi, /* 23/ 53 Hindi */ "hi" , TEXTS_hi, /* 23/ 53 Hindi */ "hi_ZZ" , TEXTS_hi_ZZ, /* 1/ 12 Hindi (ZZ) */ "hi_ZZ" , TEXTS_hi_ZZ, /* 9/134 Hindi (ZZ) */ "hr" , TEXTS_hr, /* 9/ 20 Croatian */ "hr" , TEXTS_hr, /* 9/ 20 Croatian */ "hu" , TEXTS_hu, /* 9/ 20 Hungarian */ "hu" , TEXTS_hu, /* 9/ 20 Hungarian */ "hy_AM" , TEXTS_hy_AM, /* 9/126 Armenian (Armenia) */ "hy_AM" , TEXTS_hy_AM, /* 9/126 Armenian (Armenia) */ Loading java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -167,7 +167,7 @@ public final class SubtypeLocaleUtils { return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId; return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId; } } private static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) { public static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) { if (NO_LANGUAGE.equals(localeString)) { if (NO_LANGUAGE.equals(localeString)) { return sResources.getConfiguration().locale; return sResources.getConfiguration().locale; } } Loading tests/res/values/donottranslate.xml +10 −8 Original line number Original line Diff line number Diff line Loading @@ -50,13 +50,15 @@ <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string> <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string> <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string> <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string> <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string> <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string> <string name="indirect_string">!text/multiple_chars</string> <string name="indirect_string">!string/multiple_chars</string> <string name="indirect_string_with_literal">x,!text/multiple_chars,y</string> <string name="indirect_string_with_literal">x,!string/multiple_chars,y</string> <string name="indirect2_string">!text/indirect_string</string> <string name="indirect2_string">!string/indirect_string</string> <string name="infinite_indirection">infinite,!text/infinite_indirection,loop</string> <string name="infinite_indirection">infinite,!string/infinite_indirection,loop</string> <string name="upper_indirect_string">!TEXT/MULTIPLE_CHARS</string> <string name="upper_indirect_string">!STRING/MULTIPLE_CHARS</string> <string name="upper_indirect_string_with_literal">x,!TEXT/MULTIPLE_CHARS,y</string> <string name="upper_indirect_string_with_literal">x,!STRING/MULTIPLE_CHARS,y</string> <string name="upper_indirect2_string">!TEXT/UPPER_INDIRECT_STRING</string> <string name="upper_indirect2_string">!STRING/UPPER_INDIRECT_STRING</string> <string name="upper_infinite_indirection">infinite,!TEXT/INFINITE_INDIRECTION,loop</string> <string name="upper_infinite_indirection">infinite,!STRING/INFINITE_INDIRECTION,loop</string> <string name="keyspec_indirect_navigate_actions">!fixedColumnOrder!2,!text/keyspec_action_previous,!text/keyspec_action_next</string> <string name="keyspec_indirect_navigate_actions">!fixedColumnOrder!2,!text/keyspec_action_previous,!text/keyspec_action_next</string> <string name="label_next_key">ActionNext</string> <string name="label_previous_key">ActionPrevious</string> </resources> </resources> tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyVisual; import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyVisual; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; Loading Loading @@ -64,10 +65,11 @@ abstract class KeyboardLayoutSetActionLabelBase extends KeyboardLayoutSetTestsBa } } protected static Locale getLabelLocale(final InputMethodSubtype subtype) { protected static Locale getLabelLocale(final InputMethodSubtype subtype) { if (subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)) { final String localeString = subtype.getLocale(); if (localeString.equals(SubtypeLocaleUtils.NO_LANGUAGE)) { return null; return null; } } return SubtypeLocaleUtils.getSubtypeLocale(subtype); return LocaleUtils.constructLocaleFromString(localeString); } } public void testActionUnspecified() { public void testActionUnspecified() { Loading Loading
java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +47 −45 Original line number Original line Diff line number Diff line Loading @@ -25,49 +25,42 @@ import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import java.util.HashMap; import java.util.Locale; import java.util.Locale; // TODO: Make this an immutable class. public final class KeyboardTextsSet { public final class KeyboardTextsSet { public static final String PREFIX_TEXT = "!text/"; public static final String PREFIX_TEXT = "!text/"; private static final String PREFIX_RESOURCE = "!string/"; public static final String SWITCH_TO_ALPHA_KEY_LABEL = "keylabel_to_alpha"; public static final String SWITCH_TO_ALPHA_KEY_LABEL = "keylabel_to_alpha"; private static final char BACKSLASH = Constants.CODE_BACKSLASH; private static final char BACKSLASH = Constants.CODE_BACKSLASH; private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; private static final int MAX_REFERENCE_INDIRECTION = 10; private Resources mResources; private Locale mResourceLocale; private String mResourcePackageName; private String[] mTextsTable; private String[] mTextsTable; // Resource name to text map. private HashMap<String, String> mResourceNameToTextsMap = new HashMap<>(); public void setLocale(final Locale locale, final Context context) { public void setLocale(final Locale locale, final Context context) { mTextsTable = KeyboardTextsTable.getTextsTable(locale); final Resources res = context.getResources(); final Resources res = context.getResources(); final int referenceId = context.getApplicationInfo().labelRes; final String resourcePackageName = res.getResourcePackageName(referenceId); final RunInLocale<Void> job = new RunInLocale<Void>() { @Override protected Void job(final Resources resource) { loadStringResourcesInternal(res, RESOURCE_NAMES, resourcePackageName); return null; } }; // Null means the current system locale. // Null means the current system locale. job.runInLocale(res, final String resourcePackageName = res.getResourcePackageName( SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale); context.getApplicationInfo().labelRes); setLocale(locale, res, resourcePackageName); } } @UsedForTesting @UsedForTesting void loadStringResourcesInternal(final Resources res, final String[] resourceNames, public void setLocale(final Locale locale, final Resources res, final String resourcePackageName) { final String resourcePackageName) { for (final String resName : resourceNames) { mResources = res; final int resId = res.getIdentifier(resName, "string", resourcePackageName); // Null means the current system locale. mResourceNameToTextsMap.put(resName, res.getString(resId)); mResourceLocale = SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale; } mResourcePackageName = resourcePackageName; mTextsTable = KeyboardTextsTable.getTextsTable(locale); } } public String getText(final String name) { public String getText(final String name) { final String text = mResourceNameToTextsMap.get(name); return KeyboardTextsTable.getText(name, mTextsTable); return (text != null) ? text : KeyboardTextsTable.getText(name, mTextsTable); } } private static int searchTextNameEnd(final String text, final int start) { private static int searchTextNameEnd(final String text, final int start) { Loading @@ -93,13 +86,14 @@ public final class KeyboardTextsSet { StringBuilder sb; StringBuilder sb; do { do { level++; level++; if (level >= MAX_STRING_REFERENCE_INDIRECTION) { if (level >= MAX_REFERENCE_INDIRECTION) { throw new RuntimeException("Too many " + PREFIX_TEXT + "name indirection: " + text); throw new RuntimeException("Too many " + PREFIX_TEXT + " or " + PREFIX_RESOURCE + " reference indirection: " + text); } } final int prefixLen = PREFIX_TEXT.length(); final int prefixLength = PREFIX_TEXT.length(); final int size = text.length(); final int size = text.length(); if (size < prefixLen) { if (size < prefixLength) { break; break; } } Loading @@ -110,10 +104,12 @@ public final class KeyboardTextsSet { if (sb == null) { if (sb == null) { sb = new StringBuilder(text.substring(0, pos)); sb = new StringBuilder(text.substring(0, pos)); } } final int end = searchTextNameEnd(text, pos + prefixLen); pos = expandReference(text, pos, PREFIX_TEXT, sb); final String name = text.substring(pos + prefixLen, end); } else if (text.startsWith(PREFIX_RESOURCE, pos)) { sb.append(getText(name)); if (sb == null) { pos = end - 1; sb = new StringBuilder(text.substring(0, pos)); } pos = expandReference(text, pos, PREFIX_RESOURCE, sb); } else if (c == BACKSLASH) { } else if (c == BACKSLASH) { if (sb != null) { if (sb != null) { // Append both escape character and escaped character. // Append both escape character and escaped character. Loading @@ -132,18 +128,24 @@ public final class KeyboardTextsSet { return TextUtils.isEmpty(text) ? null : text; return TextUtils.isEmpty(text) ? null : text; } } // These texts' name should be aligned with the @string/<name> in private int expandReference(final String text, final int pos, final String prefix, // values*/strings-action-keys.xml. final StringBuilder sb) { static final String[] RESOURCE_NAMES = { final int prefixLength = prefix.length(); // Labels for action. final int end = searchTextNameEnd(text, pos + prefixLength); "label_go_key", final String name = text.substring(pos + prefixLength, end); "label_send_key", if (prefix.equals(PREFIX_TEXT)) { "label_next_key", sb.append(getText(name)); "label_done_key", } else { // PREFIX_RESOURCE "label_search_key", final String resourcePackageName = mResourcePackageName; "label_previous_key", final RunInLocale<String> getTextJob = new RunInLocale<String>() { // Other labels. @Override "label_pause_key", protected String job(final Resources res) { "label_wait_key", final int resId = res.getIdentifier(name, "string", resourcePackageName); return res.getString(resId); } }; }; sb.append(getTextJob.runInLocale(mResources, mResourceLocale)); } return end - 1; } } }
java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java +78 −44 Original line number Original line Diff line number Diff line Loading @@ -209,48 +209,56 @@ public final class KeyboardTextsTable { /* 123: 1 */ "morekeys_less_than", /* 123: 1 */ "morekeys_less_than", /* 124: 1 */ "morekeys_greater_than", /* 124: 1 */ "morekeys_greater_than", /* 125: 1 */ "morekeys_exclamation", /* 125: 1 */ "morekeys_exclamation", /* 126: 0 */ "morekeys_currency_generic", /* 126: 1 */ "label_go_key", /* 127: 0 */ "morekeys_symbols_1", /* 127: 1 */ "label_send_key", /* 128: 0 */ "morekeys_symbols_2", /* 128: 1 */ "label_next_key", /* 129: 0 */ "morekeys_symbols_3", /* 129: 1 */ "label_done_key", /* 130: 0 */ "morekeys_symbols_4", /* 130: 1 */ "label_search_key", /* 131: 0 */ "morekeys_symbols_5", /* 131: 1 */ "label_previous_key", /* 132: 0 */ "morekeys_symbols_6", /* 132: 1 */ "label_pause_key", /* 133: 0 */ "morekeys_symbols_7", /* 133: 1 */ "label_wait_key", /* 134: 0 */ "morekeys_symbols_8", /* 134: 0 */ "morekeys_currency_generic", /* 135: 0 */ "morekeys_symbols_9", /* 135: 0 */ "morekeys_symbols_1", /* 136: 0 */ "morekeys_symbols_0", /* 136: 0 */ "morekeys_symbols_2", /* 137: 0 */ "morekeys_am_pm", /* 137: 0 */ "morekeys_symbols_3", /* 138: 0 */ "keyspec_settings", /* 138: 0 */ "morekeys_symbols_4", /* 139: 0 */ "keyspec_shortcut", /* 139: 0 */ "morekeys_symbols_5", /* 140: 0 */ "keyspec_action_next", /* 140: 0 */ "morekeys_symbols_6", /* 141: 0 */ "keyspec_action_previous", /* 141: 0 */ "morekeys_symbols_7", /* 142: 0 */ "keylabel_to_more_symbol", /* 142: 0 */ "morekeys_symbols_8", /* 143: 0 */ "keylabel_tablet_to_more_symbol", /* 143: 0 */ "morekeys_symbols_9", /* 144: 0 */ "keylabel_to_phone_numeric", /* 144: 0 */ "morekeys_symbols_0", /* 145: 0 */ "keylabel_to_phone_symbols", /* 145: 0 */ "morekeys_am_pm", /* 146: 0 */ "keylabel_time_am", /* 146: 0 */ "keyspec_settings", /* 147: 0 */ "keylabel_time_pm", /* 147: 0 */ "keyspec_shortcut", /* 148: 0 */ "keyspec_popular_domain", /* 148: 0 */ "keyspec_action_next", /* 149: 0 */ "morekeys_popular_domain", /* 149: 0 */ "keyspec_action_previous", /* 150: 0 */ "keyspecs_left_parenthesis_more_keys", /* 150: 0 */ "keylabel_to_more_symbol", /* 151: 0 */ "keyspecs_right_parenthesis_more_keys", /* 151: 0 */ "keylabel_tablet_to_more_symbol", /* 152: 0 */ "single_laqm_raqm", /* 152: 0 */ "keylabel_to_phone_numeric", /* 153: 0 */ "single_raqm_laqm", /* 153: 0 */ "keylabel_to_phone_symbols", /* 154: 0 */ "double_laqm_raqm", /* 154: 0 */ "keylabel_time_am", /* 155: 0 */ "double_raqm_laqm", /* 155: 0 */ "keylabel_time_pm", /* 156: 0 */ "single_lqm_rqm", /* 156: 0 */ "keyspec_popular_domain", /* 157: 0 */ "single_9qm_lqm", /* 157: 0 */ "morekeys_popular_domain", /* 158: 0 */ "single_9qm_rqm", /* 158: 0 */ "keyspecs_left_parenthesis_more_keys", /* 159: 0 */ "single_rqm_9qm", /* 159: 0 */ "keyspecs_right_parenthesis_more_keys", /* 160: 0 */ "double_lqm_rqm", /* 160: 0 */ "single_laqm_raqm", /* 161: 0 */ "double_9qm_lqm", /* 161: 0 */ "single_raqm_laqm", /* 162: 0 */ "double_9qm_rqm", /* 162: 0 */ "double_laqm_raqm", /* 163: 0 */ "double_rqm_9qm", /* 163: 0 */ "double_raqm_laqm", /* 164: 0 */ "morekeys_single_quote", /* 164: 0 */ "single_lqm_rqm", /* 165: 0 */ "morekeys_double_quote", /* 165: 0 */ "single_9qm_lqm", /* 166: 0 */ "morekeys_tablet_double_quote", /* 166: 0 */ "single_9qm_rqm", /* 167: 0 */ "keyspec_emoji_action_key", /* 167: 0 */ "single_rqm_9qm", /* 168: 0 */ "double_lqm_rqm", /* 169: 0 */ "double_9qm_lqm", /* 170: 0 */ "double_9qm_rqm", /* 171: 0 */ "double_rqm_9qm", /* 172: 0 */ "morekeys_single_quote", /* 173: 0 */ "morekeys_double_quote", /* 174: 0 */ "morekeys_tablet_double_quote", /* 175: 0 */ "keyspec_emoji_action_key", }; }; private static final String EMPTY = ""; private static final String EMPTY = ""; Loading Loading @@ -379,6 +387,14 @@ public final class KeyboardTextsTable { /* morekeys_greater_than */ "!fixedColumnOrder!3,!text/keyspec_right_single_angle_quote,!text/keyspec_greater_than_equal,!text/keyspec_right_double_angle_quote", /* morekeys_greater_than */ "!fixedColumnOrder!3,!text/keyspec_right_single_angle_quote,!text/keyspec_greater_than_equal,!text/keyspec_right_double_angle_quote", // U+00A1: "¡" INVERTED EXCLAMATION MARK // U+00A1: "¡" INVERTED EXCLAMATION MARK /* morekeys_exclamation */ "\u00A1", /* morekeys_exclamation */ "\u00A1", /* label_go_key */ "!string/label_go_key", /* label_send_key */ "!string/label_send_key", /* label_next_key */ "!string/label_next_key", /* label_done_key */ "!string/label_done_key", /* label_search_key */ "!string/label_search_key", /* label_previous_key */ "!string/label_previous_key", /* label_pause_key */ "!string/label_pause_key", /* label_wait_key */ "!string/label_wait_key", /* morekeys_currency_generic */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1", /* morekeys_currency_generic */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1", // U+00B9: "¹" SUPERSCRIPT ONE // U+00B9: "¹" SUPERSCRIPT ONE // U+00BD: "½" VULGAR FRACTION ONE HALF // U+00BD: "½" VULGAR FRACTION ONE HALF Loading Loading @@ -1885,6 +1901,24 @@ public final class KeyboardTextsTable { /* ~ morekeys_s */ /* ~ morekeys_s */ // U+20B9: "₹" INDIAN RUPEE SIGN // U+20B9: "₹" INDIAN RUPEE SIGN /* keyspec_currency */ "\u20B9", /* keyspec_currency */ "\u20B9", /* morekeys_y ~ */ 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, 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, /* ~ morekeys_exclamation */ /* label_go_key */ "Go", /* label_send_key */ "Send", /* label_next_key */ "Next", /* label_done_key */ "Done", /* label_search_key */ "Search", /* label_previous_key */ "Prev", /* label_pause_key */ "Pause", /* label_wait_key */ "Wait", }; }; /* Locale hr: Croatian */ /* Locale hr: Croatian */ Loading Loading @@ -3952,7 +3986,7 @@ public final class KeyboardTextsTable { private static final Object[] LOCALES_AND_TEXTS = { private static final Object[] LOCALES_AND_TEXTS = { // "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */ // "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */ "DEFAULT", TEXTS_DEFAULT, /* 168/168 DEFAULT */ "DEFAULT", TEXTS_DEFAULT, /* 176/176 DEFAULT */ "af" , TEXTS_af, /* 7/ 13 Afrikaans */ "af" , TEXTS_af, /* 7/ 13 Afrikaans */ "ar" , TEXTS_ar, /* 55/110 Arabic */ "ar" , TEXTS_ar, /* 55/110 Arabic */ "az_AZ" , TEXTS_az_AZ, /* 11/ 18 Azerbaijani (Azerbaijan) */ "az_AZ" , TEXTS_az_AZ, /* 11/ 18 Azerbaijani (Azerbaijan) */ Loading @@ -3974,7 +4008,7 @@ public final class KeyboardTextsTable { "fr" , TEXTS_fr, /* 13/ 62 French */ "fr" , TEXTS_fr, /* 13/ 62 French */ "gl_ES" , TEXTS_gl_ES, /* 7/ 8 Gallegan (Spain) */ "gl_ES" , TEXTS_gl_ES, /* 7/ 8 Gallegan (Spain) */ "hi" , TEXTS_hi, /* 23/ 53 Hindi */ "hi" , TEXTS_hi, /* 23/ 53 Hindi */ "hi_ZZ" , TEXTS_hi_ZZ, /* 1/ 12 Hindi (ZZ) */ "hi_ZZ" , TEXTS_hi_ZZ, /* 9/134 Hindi (ZZ) */ "hr" , TEXTS_hr, /* 9/ 20 Croatian */ "hr" , TEXTS_hr, /* 9/ 20 Croatian */ "hu" , TEXTS_hu, /* 9/ 20 Hungarian */ "hu" , TEXTS_hu, /* 9/ 20 Hungarian */ "hy_AM" , TEXTS_hy_AM, /* 9/126 Armenian (Armenia) */ "hy_AM" , TEXTS_hy_AM, /* 9/126 Armenian (Armenia) */ Loading
java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -167,7 +167,7 @@ public final class SubtypeLocaleUtils { return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId; return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId; } } private static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) { public static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) { if (NO_LANGUAGE.equals(localeString)) { if (NO_LANGUAGE.equals(localeString)) { return sResources.getConfiguration().locale; return sResources.getConfiguration().locale; } } Loading
tests/res/values/donottranslate.xml +10 −8 Original line number Original line Diff line number Diff line Loading @@ -50,13 +50,15 @@ <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string> <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string> <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string> <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string> <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string> <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string> <string name="indirect_string">!text/multiple_chars</string> <string name="indirect_string">!string/multiple_chars</string> <string name="indirect_string_with_literal">x,!text/multiple_chars,y</string> <string name="indirect_string_with_literal">x,!string/multiple_chars,y</string> <string name="indirect2_string">!text/indirect_string</string> <string name="indirect2_string">!string/indirect_string</string> <string name="infinite_indirection">infinite,!text/infinite_indirection,loop</string> <string name="infinite_indirection">infinite,!string/infinite_indirection,loop</string> <string name="upper_indirect_string">!TEXT/MULTIPLE_CHARS</string> <string name="upper_indirect_string">!STRING/MULTIPLE_CHARS</string> <string name="upper_indirect_string_with_literal">x,!TEXT/MULTIPLE_CHARS,y</string> <string name="upper_indirect_string_with_literal">x,!STRING/MULTIPLE_CHARS,y</string> <string name="upper_indirect2_string">!TEXT/UPPER_INDIRECT_STRING</string> <string name="upper_indirect2_string">!STRING/UPPER_INDIRECT_STRING</string> <string name="upper_infinite_indirection">infinite,!TEXT/INFINITE_INDIRECTION,loop</string> <string name="upper_infinite_indirection">infinite,!STRING/INFINITE_INDIRECTION,loop</string> <string name="keyspec_indirect_navigate_actions">!fixedColumnOrder!2,!text/keyspec_action_previous,!text/keyspec_action_next</string> <string name="keyspec_indirect_navigate_actions">!fixedColumnOrder!2,!text/keyspec_action_previous,!text/keyspec_action_next</string> <string name="label_next_key">ActionNext</string> <string name="label_previous_key">ActionPrevious</string> </resources> </resources>
tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyVisual; import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyVisual; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; Loading Loading @@ -64,10 +65,11 @@ abstract class KeyboardLayoutSetActionLabelBase extends KeyboardLayoutSetTestsBa } } protected static Locale getLabelLocale(final InputMethodSubtype subtype) { protected static Locale getLabelLocale(final InputMethodSubtype subtype) { if (subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)) { final String localeString = subtype.getLocale(); if (localeString.equals(SubtypeLocaleUtils.NO_LANGUAGE)) { return null; return null; } } return SubtypeLocaleUtils.getSubtypeLocale(subtype); return LocaleUtils.constructLocaleFromString(localeString); } } public void testActionUnspecified() { public void testActionUnspecified() { Loading