am aaefd566: Add !string/<resource_name> reference

* commit 'aaefd5666112c4a6fff58783c25cf9a75b468edd':
  Add !string/<resource_name> reference
main
Tadashi G. Takaoka 2014-09-25 09:47:30 +00:00 committed by Android Git Automerger
commit 4d51efce03
10 changed files with 547 additions and 295 deletions

View File

@ -25,49 +25,42 @@ import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.utils.RunInLocale;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.HashMap;
import java.util.Locale;
// TODO: Make this an immutable class.
public final class KeyboardTextsSet {
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";
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;
// Resource name to text map.
private HashMap<String, String> mResourceNameToTextsMap = new HashMap<>();
public void setLocale(final Locale locale, final Context context) {
mTextsTable = KeyboardTextsTable.getTextsTable(locale);
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.
job.runInLocale(res,
SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale);
final String resourcePackageName = res.getResourcePackageName(
context.getApplicationInfo().labelRes);
setLocale(locale, res, resourcePackageName);
}
@UsedForTesting
void loadStringResourcesInternal(final Resources res, final String[] resourceNames,
public void setLocale(final Locale locale, final Resources res,
final String resourcePackageName) {
for (final String resName : resourceNames) {
final int resId = res.getIdentifier(resName, "string", resourcePackageName);
mResourceNameToTextsMap.put(resName, res.getString(resId));
}
mResources = res;
// Null means the current system locale.
mResourceLocale = SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale;
mResourcePackageName = resourcePackageName;
mTextsTable = KeyboardTextsTable.getTextsTable(locale);
}
public String getText(final String name) {
final String text = mResourceNameToTextsMap.get(name);
return (text != null) ? text : KeyboardTextsTable.getText(name, mTextsTable);
return KeyboardTextsTable.getText(name, mTextsTable);
}
private static int searchTextNameEnd(final String text, final int start) {
@ -93,13 +86,14 @@ public final class KeyboardTextsSet {
StringBuilder sb;
do {
level++;
if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
throw new RuntimeException("Too many " + PREFIX_TEXT + "name indirection: " + text);
if (level >= MAX_REFERENCE_INDIRECTION) {
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();
if (size < prefixLen) {
if (size < prefixLength) {
break;
}
@ -110,10 +104,12 @@ public final class KeyboardTextsSet {
if (sb == null) {
sb = new StringBuilder(text.substring(0, pos));
}
final int end = searchTextNameEnd(text, pos + prefixLen);
final String name = text.substring(pos + prefixLen, end);
sb.append(getText(name));
pos = end - 1;
pos = expandReference(text, pos, PREFIX_TEXT, sb);
} else if (text.startsWith(PREFIX_RESOURCE, pos)) {
if (sb == null) {
sb = new StringBuilder(text.substring(0, pos));
}
pos = expandReference(text, pos, PREFIX_RESOURCE, sb);
} else if (c == BACKSLASH) {
if (sb != null) {
// Append both escape character and escaped character.
@ -132,18 +128,24 @@ public final class KeyboardTextsSet {
return TextUtils.isEmpty(text) ? null : text;
}
// These texts' name should be aligned with the @string/<name> in
// values*/strings-action-keys.xml.
static final String[] RESOURCE_NAMES = {
// Labels for action.
"label_go_key",
"label_send_key",
"label_next_key",
"label_done_key",
"label_search_key",
"label_previous_key",
// Other labels.
"label_pause_key",
"label_wait_key",
};
private int expandReference(final String text, final int pos, final String prefix,
final StringBuilder sb) {
final int prefixLength = prefix.length();
final int end = searchTextNameEnd(text, pos + prefixLength);
final String name = text.substring(pos + prefixLength, end);
if (prefix.equals(PREFIX_TEXT)) {
sb.append(getText(name));
} else { // PREFIX_RESOURCE
final String resourcePackageName = mResourcePackageName;
final RunInLocale<String> getTextJob = new RunInLocale<String>() {
@Override
protected String job(final Resources res) {
final int resId = res.getIdentifier(name, "string", resourcePackageName);
return res.getString(resId);
}
};
sb.append(getTextJob.runInLocale(mResources, mResourceLocale));
}
return end - 1;
}
}

View File

@ -209,48 +209,56 @@ public final class KeyboardTextsTable {
/* 123: 1 */ "morekeys_less_than",
/* 124: 1 */ "morekeys_greater_than",
/* 125: 1 */ "morekeys_exclamation",
/* 126: 0 */ "morekeys_currency_generic",
/* 127: 0 */ "morekeys_symbols_1",
/* 128: 0 */ "morekeys_symbols_2",
/* 129: 0 */ "morekeys_symbols_3",
/* 130: 0 */ "morekeys_symbols_4",
/* 131: 0 */ "morekeys_symbols_5",
/* 132: 0 */ "morekeys_symbols_6",
/* 133: 0 */ "morekeys_symbols_7",
/* 134: 0 */ "morekeys_symbols_8",
/* 135: 0 */ "morekeys_symbols_9",
/* 136: 0 */ "morekeys_symbols_0",
/* 137: 0 */ "morekeys_am_pm",
/* 138: 0 */ "keyspec_settings",
/* 139: 0 */ "keyspec_shortcut",
/* 140: 0 */ "keyspec_action_next",
/* 141: 0 */ "keyspec_action_previous",
/* 142: 0 */ "keylabel_to_more_symbol",
/* 143: 0 */ "keylabel_tablet_to_more_symbol",
/* 144: 0 */ "keylabel_to_phone_numeric",
/* 145: 0 */ "keylabel_to_phone_symbols",
/* 146: 0 */ "keylabel_time_am",
/* 147: 0 */ "keylabel_time_pm",
/* 148: 0 */ "keyspec_popular_domain",
/* 149: 0 */ "morekeys_popular_domain",
/* 150: 0 */ "keyspecs_left_parenthesis_more_keys",
/* 151: 0 */ "keyspecs_right_parenthesis_more_keys",
/* 152: 0 */ "single_laqm_raqm",
/* 153: 0 */ "single_raqm_laqm",
/* 154: 0 */ "double_laqm_raqm",
/* 155: 0 */ "double_raqm_laqm",
/* 156: 0 */ "single_lqm_rqm",
/* 157: 0 */ "single_9qm_lqm",
/* 158: 0 */ "single_9qm_rqm",
/* 159: 0 */ "single_rqm_9qm",
/* 160: 0 */ "double_lqm_rqm",
/* 161: 0 */ "double_9qm_lqm",
/* 162: 0 */ "double_9qm_rqm",
/* 163: 0 */ "double_rqm_9qm",
/* 164: 0 */ "morekeys_single_quote",
/* 165: 0 */ "morekeys_double_quote",
/* 166: 0 */ "morekeys_tablet_double_quote",
/* 167: 0 */ "keyspec_emoji_action_key",
/* 126: 1 */ "label_go_key",
/* 127: 1 */ "label_send_key",
/* 128: 1 */ "label_next_key",
/* 129: 1 */ "label_done_key",
/* 130: 1 */ "label_search_key",
/* 131: 1 */ "label_previous_key",
/* 132: 1 */ "label_pause_key",
/* 133: 1 */ "label_wait_key",
/* 134: 0 */ "morekeys_currency_generic",
/* 135: 0 */ "morekeys_symbols_1",
/* 136: 0 */ "morekeys_symbols_2",
/* 137: 0 */ "morekeys_symbols_3",
/* 138: 0 */ "morekeys_symbols_4",
/* 139: 0 */ "morekeys_symbols_5",
/* 140: 0 */ "morekeys_symbols_6",
/* 141: 0 */ "morekeys_symbols_7",
/* 142: 0 */ "morekeys_symbols_8",
/* 143: 0 */ "morekeys_symbols_9",
/* 144: 0 */ "morekeys_symbols_0",
/* 145: 0 */ "morekeys_am_pm",
/* 146: 0 */ "keyspec_settings",
/* 147: 0 */ "keyspec_shortcut",
/* 148: 0 */ "keyspec_action_next",
/* 149: 0 */ "keyspec_action_previous",
/* 150: 0 */ "keylabel_to_more_symbol",
/* 151: 0 */ "keylabel_tablet_to_more_symbol",
/* 152: 0 */ "keylabel_to_phone_numeric",
/* 153: 0 */ "keylabel_to_phone_symbols",
/* 154: 0 */ "keylabel_time_am",
/* 155: 0 */ "keylabel_time_pm",
/* 156: 0 */ "keyspec_popular_domain",
/* 157: 0 */ "morekeys_popular_domain",
/* 158: 0 */ "keyspecs_left_parenthesis_more_keys",
/* 159: 0 */ "keyspecs_right_parenthesis_more_keys",
/* 160: 0 */ "single_laqm_raqm",
/* 161: 0 */ "single_raqm_laqm",
/* 162: 0 */ "double_laqm_raqm",
/* 163: 0 */ "double_raqm_laqm",
/* 164: 0 */ "single_lqm_rqm",
/* 165: 0 */ "single_9qm_lqm",
/* 166: 0 */ "single_9qm_rqm",
/* 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 = "";
@ -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",
// U+00A1: "¡" INVERTED EXCLAMATION MARK
/* 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",
// U+00B9: "¹" SUPERSCRIPT ONE
// U+00BD: "½" VULGAR FRACTION ONE HALF
@ -1885,6 +1901,24 @@ public final class KeyboardTextsTable {
/* ~ morekeys_s */
// U+20B9: "₹" INDIAN RUPEE SIGN
/* 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 */
@ -3952,7 +3986,7 @@ public final class KeyboardTextsTable {
private static final Object[] LOCALES_AND_TEXTS = {
// "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */
"DEFAULT", TEXTS_DEFAULT, /* 168/168 DEFAULT */
"DEFAULT", TEXTS_DEFAULT, /* 176/176 DEFAULT */
"af" , TEXTS_af, /* 7/ 13 Afrikaans */
"ar" , TEXTS_ar, /* 55/110 Arabic */
"az_AZ" , TEXTS_az_AZ, /* 11/ 18 Azerbaijani (Azerbaijan) */
@ -3974,7 +4008,7 @@ public final class KeyboardTextsTable {
"fr" , TEXTS_fr, /* 13/ 62 French */
"gl_ES" , TEXTS_gl_ES, /* 7/ 8 Gallegan (Spain) */
"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 */
"hu" , TEXTS_hu, /* 9/ 20 Hungarian */
"hy_AM" , TEXTS_hy_AM, /* 9/126 Armenian (Armenia) */

View File

@ -167,7 +167,7 @@ public final class SubtypeLocaleUtils {
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)) {
return sResources.getConfiguration().locale;
}

View File

@ -50,13 +50,15 @@
<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_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string>
<string name="indirect_string">!text/multiple_chars</string>
<string name="indirect_string_with_literal">x,!text/multiple_chars,y</string>
<string name="indirect2_string">!text/indirect_string</string>
<string name="infinite_indirection">infinite,!text/infinite_indirection,loop</string>
<string name="upper_indirect_string">!TEXT/MULTIPLE_CHARS</string>
<string name="upper_indirect_string_with_literal">x,!TEXT/MULTIPLE_CHARS,y</string>
<string name="upper_indirect2_string">!TEXT/UPPER_INDIRECT_STRING</string>
<string name="upper_infinite_indirection">infinite,!TEXT/INFINITE_INDIRECTION,loop</string>
<string name="indirect_string">!string/multiple_chars</string>
<string name="indirect_string_with_literal">x,!string/multiple_chars,y</string>
<string name="indirect2_string">!string/indirect_string</string>
<string name="infinite_indirection">infinite,!string/infinite_indirection,loop</string>
<string name="upper_indirect_string">!STRING/MULTIPLE_CHARS</string>
<string name="upper_indirect_string_with_literal">x,!STRING/MULTIPLE_CHARS,y</string>
<string name="upper_indirect2_string">!STRING/UPPER_INDIRECT_STRING</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="label_next_key">ActionNext</string>
<string name="label_previous_key">ActionPrevious</string>
</resources>

View File

@ -25,6 +25,7 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyVisual;
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.SubtypeLocaleUtils;
@ -64,10 +65,11 @@ abstract class KeyboardLayoutSetActionLabelBase extends KeyboardLayoutSetTestsBa
}
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 SubtypeLocaleUtils.getSubtypeLocale(subtype);
return LocaleUtils.constructLocaleFromString(localeString);
}
public void testActionUnspecified() {

View File

@ -22,15 +22,40 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.keyboard.internal.KeyboardTextsSet;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodManager;
import com.android.inputmethod.latin.utils.RunInLocale;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.ArrayList;
import java.util.Locale;
@MediumTest
public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActionLabelBase {
// Filter a subtype whose name should be displayed using {@link Locale#ROOT}, such like
// Hinglish (hi_ZZ) and Serbian-Latn (sr_ZZ).
static final SubtypeFilter SUBTYPE_FILTER_NAME_IN_BASE_LOCALE = new SubtypeFilter() {
@Override
public boolean accept(final InputMethodSubtype subtype) {
return Locale.ROOT.equals(
SubtypeLocaleUtils.getDisplayLocaleOfSubtypeLocale(subtype.getLocale()));
}
};
private ArrayList<InputMethodSubtype> mSubtypesWhoseNameIsDisplayedInItsLocale;
@Override
protected void setUp() throws Exception {
super.setUp();
mSubtypesWhoseNameIsDisplayedInItsLocale = getSubtypesFilteredBy(new SubtypeFilter() {
@Override
public boolean accept(final InputMethodSubtype subtype) {
return !SUBTYPE_FILTER_NAME_IN_BASE_LOCALE.accept(subtype);
}
});
}
@Override
protected int getKeyboardThemeForTests() {
return KeyboardTheme.THEME_ID_KLP;
@ -38,7 +63,7 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
@Override
public void testActionGo() {
for (final InputMethodSubtype subtype : getAllSubtypesList()) {
for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
R.string.label_go_key, getLabelLocale(subtype), getContext());
@ -48,7 +73,7 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
@Override
public void testActionSend() {
for (final InputMethodSubtype subtype : getAllSubtypesList()) {
for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
R.string.label_send_key, getLabelLocale(subtype), getContext());
@ -58,7 +83,7 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
@Override
public void testActionNext() {
for (final InputMethodSubtype subtype : getAllSubtypesList()) {
for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
R.string.label_next_key, getLabelLocale(subtype), getContext());
@ -68,7 +93,7 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
@Override
public void testActionDone() {
for (final InputMethodSubtype subtype : getAllSubtypesList()) {
for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
R.string.label_done_key, getLabelLocale(subtype), getContext());
@ -78,7 +103,7 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
@Override
public void testActionPrevious() {
for (final InputMethodSubtype subtype : getAllSubtypesList()) {
for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
R.string.label_previous_key, getLabelLocale(subtype), getContext());
@ -105,7 +130,7 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
// Working variable to simulate system locale changing.
private Locale mSystemLocale = Locale.getDefault();
private void doTestActionKeysInLocale(final InputMethodSubtype subtype,
private void doTestActionKeysInLocaleWithStringResources(final InputMethodSubtype subtype,
final Locale labelLocale, final Locale systemLocale) {
// Simulate system locale changing, see {@link SystemBroadcastReceiver}.
if (!systemLocale.equals(mSystemLocale)) {
@ -144,10 +169,10 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
final InputMethodSubtype italian = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
Locale.ITALIAN.toString(), SubtypeLocaleUtils.QWERTY);
// An action label should be displayed in subtype's locale regardless of the system locale.
doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.US);
doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.FRENCH);
doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.ITALIAN);
doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.JAPANESE);
doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.US);
doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.FRENCH);
doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.ITALIAN);
doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.JAPANESE);
}
public void testNoLanguageSubtypeActionLabel() {
@ -155,9 +180,58 @@ public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActio
final InputMethodSubtype noLanguage = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
// An action label of no language keyboard should be displayed in the system locale.
doTestActionKeysInLocale(noLanguage, Locale.US, Locale.US);
doTestActionKeysInLocale(noLanguage, Locale.FRENCH, Locale.FRENCH);
doTestActionKeysInLocale(noLanguage, Locale.ITALIAN, Locale.ITALIAN);
doTestActionKeysInLocale(noLanguage, Locale.JAPANESE, Locale.JAPANESE);
doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.US, Locale.US);
doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.FRENCH, Locale.FRENCH);
doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.ITALIAN, Locale.ITALIAN);
doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.JAPANESE, Locale.JAPANESE);
}
private void doTestActionKeysInLocaleWithKeyboardTextsSet(final InputMethodSubtype subtype,
final Locale labelLocale, final Locale systemLocale) {
// Simulate system locale changing, see {@link SystemBroadcastReceiver}.
if (!systemLocale.equals(mSystemLocale)) {
KeyboardLayoutSet.onSystemLocaleChanged();
mSystemLocale = systemLocale;
}
final KeyboardTextsSet textsSet = new KeyboardTextsSet();
textsSet.setLocale(labelLocale, getContext());
final ExpectedActionKey enterKey = ExpectedActionKey.newIconKey(
KeyboardIconsSet.NAME_ENTER_KEY);
final ExpectedActionKey goKey = ExpectedActionKey.newLabelKey(
textsSet.getText("label_go_key"));
final ExpectedActionKey searchKey = ExpectedActionKey.newIconKey(
KeyboardIconsSet.NAME_SEARCH_KEY);
final ExpectedActionKey sendKey = ExpectedActionKey.newLabelKey(
textsSet.getText("label_send_key"));
final ExpectedActionKey nextKey = ExpectedActionKey.newLabelKey(
textsSet.getText("label_next_key"));
final ExpectedActionKey doneKey = ExpectedActionKey.newLabelKey(
textsSet.getText("label_done_key"));
final ExpectedActionKey previousKey = ExpectedActionKey.newLabelKey(
textsSet.getText("label_previous_key"));
final String tag = "label=hi_ZZ system=" + systemLocale
+ " " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
final RunInLocale<Void> job = new RunInLocale<Void>() {
@Override
public Void job(final Resources res) {
doTestActionKeys(subtype, tag, enterKey, enterKey, goKey, searchKey, sendKey,
nextKey, doneKey, previousKey);
return null;
}
};
job.runInLocale(getContext().getResources(), systemLocale);
}
public void testHinglishActionLabel() {
final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
final Locale hi_ZZ = new Locale("hi", "ZZ");
final InputMethodSubtype hinglish = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
hi_ZZ.toString(), SubtypeLocaleUtils.QWERTY);
// An action label should be displayed in subtype's locale regardless of the system locale.
doTestActionKeysInLocaleWithKeyboardTextsSet(hinglish, hi_ZZ, hi_ZZ);
doTestActionKeysInLocaleWithKeyboardTextsSet(hinglish, hi_ZZ, Locale.US);
doTestActionKeysInLocaleWithKeyboardTextsSet(hinglish, hi_ZZ, Locale.FRENCH);
doTestActionKeysInLocaleWithKeyboardTextsSet(hinglish, hi_ZZ, Locale.ITALIAN);
doTestActionKeysInLocaleWithKeyboardTextsSet(hinglish, hi_ZZ, Locale.JAPANESE);
}
}

View File

@ -16,52 +16,33 @@
package com.android.inputmethod.keyboard.internal;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Resources;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.inputmethod.latin.R;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
@MediumTest
public class MoreKeySpecSplitTests extends InstrumentationTestCase {
@SmallTest
public class MoreKeySpecSplitTests extends AndroidTestCase {
private static final Locale TEST_LOCALE = Locale.ENGLISH;
final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
private final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
@Override
protected void setUp() throws Exception {
super.setUp();
final Instrumentation instrumentation = getInstrumentation();
final Context targetContext = instrumentation.getTargetContext();
mTextsSet.setLocale(TEST_LOCALE, targetContext);
final String[] testResourceNames = getAllResourceIdNames(
com.android.inputmethod.latin.tests.R.string.class);
final Context testContext = instrumentation.getContext();
final Resources testRes = testContext.getResources();
final String testResPackageName = testRes.getResourcePackageName(
// This dummy raw resource is needed to be able to load string resources from a test
// APK successfully.
com.android.inputmethod.latin.tests.R.raw.dummy_resource_for_testing);
mTextsSet.loadStringResourcesInternal(testRes, testResourceNames, testResPackageName);
final Context targetContext = getContext();
final Resources targetRes = targetContext.getResources();
final String targetPackageName = targetRes.getResourcePackageName(
R.string.english_ime_name);
mTextsSet.setLocale(TEST_LOCALE, targetRes, targetPackageName);
}
private static String[] getAllResourceIdNames(final Class<?> resourceIdClass) {
final ArrayList<String> names = new ArrayList<>();
for (final Field field : resourceIdClass.getFields()) {
if (field.getType() == int.class) {
names.add(field.getName());
}
}
return names.toArray(new String[names.size()]);
}
private static <T> void assertArrayEquals(final String message, final T[] expected,
final T[] actual) {
static <T> void assertArrayEquals(final String message, final T[] expected, final T[] actual) {
if (expected == actual) {
return;
}
@ -109,14 +90,6 @@ public class MoreKeySpecSplitTests extends InstrumentationTestCase {
private static final String SURROGATE1 = PAIR1 + PAIR2;
private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3;
public void testResolveNullText() {
assertNull("resolve null", mTextsSet.resolveTextReference(null));
}
public void testResolveEmptyText() {
assertNull("resolve empty text", mTextsSet.resolveTextReference("!text/empty_string"));
}
public void testSplitZero() {
assertTextArray("Empty string", "");
assertTextArray("Empty entry", ",");
@ -224,132 +197,14 @@ public class MoreKeySpecSplitTests extends InstrumentationTestCase {
"\\!", "\\!TEXT/EMPTY_STRING");
}
public void testSplitResourceError() {
assertError("Incomplete resource name", "!text/", "!text/");
assertError("Non existing resource", "!text/non_existing");
public void testSplitTextReferenceError() {
assertError("Incomplete text name", "!text/", "!text/");
assertError("Non existing text", "!text/non_existing");
}
public void testSplitResourceZero() {
assertTextArray("Empty string",
"!text/empty_string");
}
public void testSplitResourceSingle() {
assertTextArray("Single char",
"!text/single_char", "a");
assertTextArray("Space",
"!text/space", " ");
assertTextArray("Single label",
"!text/single_label", "abc");
assertTextArray("Spaces",
"!text/spaces", " ");
assertTextArray("Spaces in label",
"!text/spaces_in_label", "a b c");
assertTextArray("Spaces at beginning of label",
"!text/spaces_at_beginning_of_label", " abc");
assertTextArray("Spaces at end of label",
"!text/spaces_at_end_of_label", "abc ");
assertTextArray("label surrounded by spaces",
"!text/label_surrounded_by_spaces", " abc ");
assertTextArray("Escape and single char",
"\\\\!text/single_char", "\\\\a");
}
public void testSplitResourceSingleEscaped() {
assertTextArray("Escaped char",
"!text/escaped_char", "\\a");
assertTextArray("Escaped comma",
"!text/escaped_comma", "\\,");
assertTextArray("Escaped comma escape",
"!text/escaped_comma_escape", "a\\,\\");
assertTextArray("Escaped escape",
"!text/escaped_escape", "\\\\");
assertTextArray("Escaped label",
"!text/escaped_label", "a\\bc");
assertTextArray("Escaped label at beginning",
"!text/escaped_label_at_beginning", "\\abc");
assertTextArray("Escaped label at end",
"!text/escaped_label_at_end", "abc\\");
assertTextArray("Escaped label with comma",
"!text/escaped_label_with_comma", "a\\,c");
assertTextArray("Escaped label with comma at beginning",
"!text/escaped_label_with_comma_at_beginning", "\\,bc");
assertTextArray("Escaped label with comma at end",
"!text/escaped_label_with_comma_at_end", "ab\\,");
assertTextArray("Escaped label with successive",
"!text/escaped_label_with_successive", "\\,\\\\bc");
assertTextArray("Escaped label with escape",
"!text/escaped_label_with_escape", "a\\\\c");
}
public void testSplitResourceMulti() {
assertTextArray("Multiple chars",
"!text/multiple_chars", "a", "b", "c");
assertTextArray("Multiple chars surrounded by spaces",
"!text/multiple_chars_surrounded_by_spaces",
" a ", " b ", " c ");
assertTextArray("Multiple labels",
"!text/multiple_labels", "abc", "def", "ghi");
assertTextArray("Multiple labels surrounded by spaces",
"!text/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi ");
}
public void testSplitResourcetMultiEscaped() {
assertTextArray("Multiple chars with comma",
"!text/multiple_chars_with_comma",
"a", "\\,", "c");
assertTextArray("Multiple chars with comma surrounded by spaces",
"!text/multiple_chars_with_comma_surrounded_by_spaces",
" a ", " \\, ", " c ");
assertTextArray("Multiple labels with escape",
"!text/multiple_labels_with_escape",
"\\abc", "d\\ef", "gh\\i");
assertTextArray("Multiple labels with escape surrounded by spaces",
"!text/multiple_labels_with_escape_surrounded_by_spaces",
" \\abc ", " d\\ef ", " gh\\i ");
assertTextArray("Multiple labels with comma and escape",
"!text/multiple_labels_with_comma_and_escape",
"ab\\\\", "d\\\\\\,", "g\\,i");
assertTextArray("Multiple labels with comma and escape surrounded by spaces",
"!text/multiple_labels_with_comma_and_escape_surrounded_by_spaces",
" ab\\\\ ", " d\\\\\\, ", " g\\,i ");
}
public void testSplitMultipleResources() {
assertTextArray("Literals and resources",
"1,!text/multiple_chars,z", "1", "a", "b", "c", "z");
assertTextArray("Literals and resources and escape at end",
"\\1,!text/multiple_chars,z\\", "\\1", "a", "b", "c", "z\\");
assertTextArray("Multiple single resource chars and labels",
"!text/single_char,!text/single_label,!text/escaped_comma",
"a", "abc", "\\,");
assertTextArray("Multiple single resource chars and labels 2",
"!text/single_char,!text/single_label,!text/escaped_comma_escape",
"a", "abc", "a\\,\\");
assertTextArray("Multiple multiple resource chars and labels",
"!text/multiple_chars,!text/multiple_labels,!text/multiple_chars_with_comma",
"a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c");
assertTextArray("Concatenated resources",
"!text/multiple_chars!text/multiple_labels!text/multiple_chars_with_comma",
"a", "b", "cabc", "def", "ghia", "\\,", "c");
assertTextArray("Concatenated resource and literal",
"abc!text/multiple_labels",
"abcabc", "def", "ghi");
}
public void testSplitIndirectReference() {
assertTextArray("Indirect",
"!text/indirect_string", "a", "b", "c");
assertTextArray("Indirect with literal",
"1,!text/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2");
assertTextArray("Indirect2",
"!text/indirect2_string", "a", "b", "c");
}
public void testSplitInfiniteIndirectReference() {
assertError("Infinite indirection",
"1,!text/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
public void testSplitEmptyTextReference() {
// Note that morekeys_q of English locale is empty.
assertTextArray("Empty string", "!text/morekeys_q");
}
public void testLabelReferece() {
@ -360,12 +215,6 @@ public class MoreKeySpecSplitTests extends InstrumentationTestCase {
assertTextArray("Settings as more key", "!text/keyspec_settings",
"!icon/settings_key|!code/key_settings");
assertTextArray("Indirect naviagte actions as more key",
"!text/keyspec_indirect_navigate_actions",
"!fixedColumnOrder!2",
"!hasLabels!", "Prev|!code/key_action_previous",
"!hasLabels!", "Next|!code/key_action_next");
}
public void testUselessUpperCaseSpecifier() {
@ -394,14 +243,6 @@ public class MoreKeySpecSplitTests extends InstrumentationTestCase {
assertTextArray("INDIRECT2",
"!TEXT/INDIRECT2_STRING", "!TEXT/INDIRECT2_STRING");
assertTextArray("Upper indirect",
"!text/upper_indirect_string", "!TEXT/MULTIPLE_CHARS");
assertTextArray("Upper indirect with literal",
"1,!text/upper_indirect_string_with_literal,2",
"1", "x", "!TEXT/MULTIPLE_CHARS", "y", "2");
assertTextArray("Upper indirect2",
"!text/upper_indirect2_string", "!TEXT/UPPER_INDIRECT_STRING");
assertTextArray("UPPER INDIRECT",
"!TEXT/upper_INDIRECT_STRING", "!TEXT/upper_INDIRECT_STRING");
assertTextArray("Upper INDIRECT with literal",
@ -413,9 +254,6 @@ public class MoreKeySpecSplitTests extends InstrumentationTestCase {
assertTextArray("INFINITE INDIRECTION",
"1,!TEXT/INFINITE_INDIRECTION,2", "1", "!TEXT/INFINITE_INDIRECTION", "2");
assertTextArray("Upper infinite indirection",
"1,!text/upper_infinite_indirection,2",
"1", "infinite", "!TEXT/INFINITE_INDIRECTION", "loop", "2");
assertTextArray("Upper INFINITE INDIRECTION",
"1,!TEXT/UPPER_INFINITE_INDIRECTION,2",
"1", "!TEXT/UPPER_INFINITE_INDIRECTION", "2");

View File

@ -0,0 +1,284 @@
/*
* Copyright (C) 2014 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.app.Instrumentation;
import android.content.Context;
import android.content.res.Resources;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.inputmethod.latin.tests.R;
import java.util.Locale;
@SmallTest
public class MoreKeySpecStringReferenceTests extends InstrumentationTestCase {
private static final Locale TEST_LOCALE = Locale.ENGLISH;
private final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
@Override
protected void setUp() throws Exception {
super.setUp();
final Instrumentation instrumentation = getInstrumentation();
final Context testContext = instrumentation.getContext();
final Resources testRes = testContext.getResources();
final String testPackageName = testRes.getResourcePackageName(R.string.empty_string);
mTextsSet.setLocale(TEST_LOCALE, testRes, testPackageName);
}
private void assertTextArray(final String message, final String value,
final String ... expectedArray) {
final String resolvedActual = mTextsSet.resolveTextReference(value);
final String[] actual = MoreKeySpec.splitKeySpecs(resolvedActual);
final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
MoreKeySpecSplitTests.assertArrayEquals(message, expected, actual);
}
private void assertError(final String message, final String value, final String ... expected) {
try {
assertTextArray(message, value, expected);
fail(message);
} catch (Exception pcpe) {
// success.
}
}
public void testResolveNullText() {
assertEquals("resolve null",
mTextsSet.resolveTextReference(null), null);
}
public void testResolveEmptyText() {
assertEquals("resolve empty text",
mTextsSet.resolveTextReference("!string/empty_string"), null);
}
public void testSplitSingleEscaped() {
assertTextArray("Escaped !string", "\\!string",
"\\!string");
assertTextArray("Escaped !string/", "\\!string/",
"\\!string/");
assertTextArray("Escaped !STRING/", "\\!STRING/",
"\\!STRING/");
assertTextArray("Escaped !string/name", "\\!string/empty_string",
"\\!string/empty_string");
assertTextArray("Escaped !STRING/NAME", "\\!STRING/EMPTY_STRING",
"\\!STRING/EMPTY_STRING");
}
public void testSplitMultiEscaped() {
assertTextArray("Multiple escaped !string", "\\!,\\!string/empty_string",
"\\!", "\\!string/empty_string");
assertTextArray("Multiple escaped !STRING", "\\!,\\!STRING/EMPTY_STRING",
"\\!", "\\!STRING/EMPTY_STRING");
}
public void testSplitStringReferenceError() {
assertError("Incomplete resource name", "!string/", "!string/");
assertError("Non existing resource", "!string/non_existing");
}
public void testSplitEmptyStringReference() {
assertTextArray("Empty string", "!string/empty_string");
}
public void testSplitResourceSingle() {
assertTextArray("Single char", "!string/single_char",
"a");
assertTextArray("Space", "!string/space",
" ");
assertTextArray("Single label", "!string/single_label",
"abc");
assertTextArray("Spaces", "!string/spaces",
" ");
assertTextArray("Spaces in label", "!string/spaces_in_label",
"a b c");
assertTextArray("Spaces at beginning of label", "!string/spaces_at_beginning_of_label",
" abc");
assertTextArray("Spaces at end of label", "!string/spaces_at_end_of_label",
"abc ");
assertTextArray("label surrounded by spaces", "!string/label_surrounded_by_spaces",
" abc ");
assertTextArray("Escape and single char", "\\\\!string/single_char",
"\\\\a");
}
public void testSplitResourceSingleEscaped() {
assertTextArray("Escaped char",
"!string/escaped_char", "\\a");
assertTextArray("Escaped comma",
"!string/escaped_comma", "\\,");
assertTextArray("Escaped comma escape",
"!string/escaped_comma_escape", "a\\,\\");
assertTextArray("Escaped escape",
"!string/escaped_escape", "\\\\");
assertTextArray("Escaped label",
"!string/escaped_label", "a\\bc");
assertTextArray("Escaped label at beginning",
"!string/escaped_label_at_beginning", "\\abc");
assertTextArray("Escaped label at end",
"!string/escaped_label_at_end", "abc\\");
assertTextArray("Escaped label with comma",
"!string/escaped_label_with_comma", "a\\,c");
assertTextArray("Escaped label with comma at beginning",
"!string/escaped_label_with_comma_at_beginning", "\\,bc");
assertTextArray("Escaped label with comma at end",
"!string/escaped_label_with_comma_at_end", "ab\\,");
assertTextArray("Escaped label with successive",
"!string/escaped_label_with_successive", "\\,\\\\bc");
assertTextArray("Escaped label with escape",
"!string/escaped_label_with_escape", "a\\\\c");
}
public void testSplitResourceMulti() {
assertTextArray("Multiple chars",
"!string/multiple_chars", "a", "b", "c");
assertTextArray("Multiple chars surrounded by spaces",
"!string/multiple_chars_surrounded_by_spaces",
" a ", " b ", " c ");
assertTextArray("Multiple labels",
"!string/multiple_labels", "abc", "def", "ghi");
assertTextArray("Multiple labels surrounded by spaces",
"!string/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi ");
}
public void testSplitResourcetMultiEscaped() {
assertTextArray("Multiple chars with comma",
"!string/multiple_chars_with_comma",
"a", "\\,", "c");
assertTextArray("Multiple chars with comma surrounded by spaces",
"!string/multiple_chars_with_comma_surrounded_by_spaces",
" a ", " \\, ", " c ");
assertTextArray("Multiple labels with escape",
"!string/multiple_labels_with_escape",
"\\abc", "d\\ef", "gh\\i");
assertTextArray("Multiple labels with escape surrounded by spaces",
"!string/multiple_labels_with_escape_surrounded_by_spaces",
" \\abc ", " d\\ef ", " gh\\i ");
assertTextArray("Multiple labels with comma and escape",
"!string/multiple_labels_with_comma_and_escape",
"ab\\\\", "d\\\\\\,", "g\\,i");
assertTextArray("Multiple labels with comma and escape surrounded by spaces",
"!string/multiple_labels_with_comma_and_escape_surrounded_by_spaces",
" ab\\\\ ", " d\\\\\\, ", " g\\,i ");
}
public void testSplitMultipleResources() {
assertTextArray("Literals and resources",
"1,!string/multiple_chars,z",
"1", "a", "b", "c", "z");
assertTextArray("Literals and resources and escape at end",
"\\1,!string/multiple_chars,z\\",
"\\1", "a", "b", "c", "z\\");
assertTextArray("Multiple single resource chars and labels",
"!string/single_char,!string/single_label,!string/escaped_comma",
"a", "abc", "\\,");
assertTextArray("Multiple single resource chars and labels 2",
"!string/single_char,!string/single_label,!string/escaped_comma_escape",
"a", "abc", "a\\,\\");
assertTextArray("Multiple multiple resource chars and labels",
"!string/multiple_chars,!string/multiple_labels,!string/multiple_chars_with_comma",
"a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c");
assertTextArray("Concatenated resources",
"!string/multiple_chars!string/multiple_labels!string/multiple_chars_with_comma",
"a", "b", "cabc", "def", "ghia", "\\,", "c");
assertTextArray("Concatenated resource and literal",
"abc!string/multiple_labels",
"abcabc", "def", "ghi");
}
public void testSplitIndirectReference() {
assertTextArray("Indirect",
"!string/indirect_string", "a", "b", "c");
assertTextArray("Indirect with literal",
"1,!string/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2");
assertTextArray("Indirect2",
"!string/indirect2_string", "a", "b", "c");
}
public void testSplitInfiniteIndirectReference() {
assertError("Infinite indirection",
"1,!string/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
}
public void testLabelReferece() {
assertTextArray("Indirect naviagte actions as more key",
"!string/keyspec_indirect_navigate_actions",
"!fixedColumnOrder!2",
"!hasLabels!", "ActionPrevious|!code/key_action_previous",
"!hasLabels!", "ActionNext|!code/key_action_next");
}
public void testUselessUpperCaseSpecifier() {
assertTextArray("EMPTY STRING",
"!STRING/EMPTY_STRING", "!STRING/EMPTY_STRING");
assertTextArray("SINGLE CHAR",
"!STRING/SINGLE_CHAR", "!STRING/SINGLE_CHAR");
assertTextArray("Escape and SINGLE CHAR",
"\\\\!STRING/SINGLE_CHAR", "\\\\!STRING/SINGLE_CHAR");
assertTextArray("MULTIPLE CHARS",
"!STRING/MULTIPLE_CHARS", "!STRING/MULTIPLE_CHARS");
assertTextArray("Literals and RESOURCES",
"1,!STRING/MULTIPLE_CHARS,z", "1", "!STRING/MULTIPLE_CHARS", "z");
assertTextArray("Multiple single RESOURCE chars and LABELS 2",
"!STRING/SINGLE_CHAR,!STRING/SINGLE_LABEL,!STRING/ESCAPED_COMMA_ESCAPE",
"!STRING/SINGLE_CHAR", "!STRING/SINGLE_LABEL", "!STRING/ESCAPED_COMMA_ESCAPE");
assertTextArray("INDIRECT",
"!STRING/INDIRECT_STRING", "!STRING/INDIRECT_STRING");
assertTextArray("INDIRECT with literal",
"1,!STRING/INDIRECT_STRING_WITH_LITERAL,2",
"1", "!STRING/INDIRECT_STRING_WITH_LITERAL", "2");
assertTextArray("INDIRECT2",
"!STRING/INDIRECT2_STRING", "!STRING/INDIRECT2_STRING");
assertTextArray("Upper indirect",
"!string/upper_indirect_string", "!STRING/MULTIPLE_CHARS");
assertTextArray("Upper indirect with literal",
"1,!string/upper_indirect_string_with_literal,2",
"1", "x", "!STRING/MULTIPLE_CHARS", "y", "2");
assertTextArray("Upper indirect2",
"!string/upper_indirect2_string", "!STRING/UPPER_INDIRECT_STRING");
assertTextArray("UPPER INDIRECT",
"!STRING/upper_INDIRECT_STRING", "!STRING/upper_INDIRECT_STRING");
assertTextArray("Upper INDIRECT with literal",
"1,!STRING/upper_INDIRECT_STRING_WITH_LITERAL,2",
"1", "!STRING/upper_INDIRECT_STRING_WITH_LITERAL", "2");
assertTextArray("Upper INDIRECT2",
"!STRING/upper_INDIRECT2_STRING", "!STRING/upper_INDIRECT2_STRING");
assertTextArray("INFINITE INDIRECTION",
"1,!STRING/INFINITE_INDIRECTION,2", "1", "!STRING/INFINITE_INDIRECTION", "2");
assertTextArray("Upper infinite indirection",
"1,!string/upper_infinite_indirection,2",
"1", "infinite", "!STRING/INFINITE_INDIRECTION", "loop", "2");
assertTextArray("Upper INFINITE INDIRECTION",
"1,!STRING/UPPER_INFINITE_INDIRECTION,2",
"1", "!STRING/UPPER_INFINITE_INDIRECTION", "2");
assertTextArray("INDIRECT NAVIGATE ACTIONS AS MORE KEY",
"!STRING/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY",
"!STRING/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY");
}
}

View File

@ -20,4 +20,12 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- U+20B9: "₹" INDIAN RUPEE SIGN -->
<string name="keyspec_currency">&#x20B9;</string>
<string name="label_go_key">Go</string>
<string name="label_send_key">Send</string>
<string name="label_next_key">Next</string>
<string name="label_done_key">Done</string>
<string name="label_search_key">Search</string>
<string name="label_previous_key">Prev</string>
<string name="label_pause_key">Pause</string>
<string name="label_wait_key">Wait</string>
</resources>

View File

@ -259,4 +259,12 @@
<string name="morekeys_double_quote">!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes</string>
<string name="morekeys_tablet_double_quote">!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes</string>
<string name="keyspec_emoji_action_key">!icon/emoji_action_key|!code/key_emoji</string>
<string name="label_go_key">!string/label_go_key</string>
<string name="label_send_key">!string/label_send_key</string>
<string name="label_next_key">!string/label_next_key</string>
<string name="label_done_key">!string/label_done_key</string>
<string name="label_search_key">!string/label_search_key</string>
<string name="label_previous_key">!string/label_previous_key</string>
<string name="label_pause_key">!string/label_pause_key</string>
<string name="label_wait_key">!string/label_wait_key</string>
</resources>