aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/AndroidManifest.xml12
-rw-r--r--java/res/drawable-hdpi/ic_settings_language.pngbin0 -> 986 bytes
-rw-r--r--java/res/drawable-hdpi/ic_setup_wizard.pngbin0 -> 702 bytes
-rw-r--r--java/res/drawable-mdpi/ic_settings_language.pngbin0 -> 756 bytes
-rw-r--r--java/res/drawable-mdpi/ic_setup_wizard.pngbin0 -> 626 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_settings_language.pngbin0 -> 1267 bytes
-rw-r--r--java/res/drawable-xhdpi/ic_setup_wizard.pngbin0 -> 737 bytes
-rw-r--r--java/res/drawable-xxhdpi/ic_setup_wizard.pngbin0 -> 892 bytes
-rw-r--r--java/res/layout/input_view.xml6
-rw-r--r--java/res/layout/setup_step.xml58
-rw-r--r--java/res/layout/setup_wizard.xml78
-rw-r--r--java/res/values-af/strings.xml2
-rw-r--r--java/res/values-am/strings.xml2
-rw-r--r--java/res/values-ar/strings.xml2
-rw-r--r--java/res/values-be/strings.xml2
-rw-r--r--java/res/values-bg/strings.xml2
-rw-r--r--java/res/values-ca/strings.xml2
-rw-r--r--java/res/values-cs/strings.xml2
-rw-r--r--java/res/values-da/strings.xml2
-rw-r--r--java/res/values-de/strings.xml2
-rw-r--r--java/res/values-el/strings.xml2
-rw-r--r--java/res/values-en-rGB/strings.xml2
-rw-r--r--java/res/values-es-rUS/strings.xml2
-rw-r--r--java/res/values-es/strings.xml2
-rw-r--r--java/res/values-et/strings.xml2
-rw-r--r--java/res/values-fa/strings.xml2
-rw-r--r--java/res/values-fi/strings.xml2
-rw-r--r--java/res/values-fr/strings.xml2
-rw-r--r--java/res/values-hi/strings.xml2
-rw-r--r--java/res/values-hr/strings.xml2
-rw-r--r--java/res/values-hu/strings.xml2
-rw-r--r--java/res/values-in/strings.xml2
-rw-r--r--java/res/values-is/strings.xml292
-rw-r--r--java/res/values-it/strings.xml2
-rw-r--r--java/res/values-iw/strings.xml2
-rw-r--r--java/res/values-ja/strings.xml2
-rw-r--r--java/res/values-ka/strings.xml292
-rw-r--r--java/res/values-ko/strings.xml2
-rw-r--r--java/res/values-lt/strings.xml2
-rw-r--r--java/res/values-lv/strings.xml2
-rw-r--r--java/res/values-mk/strings.xml292
-rw-r--r--java/res/values-mn/strings.xml292
-rw-r--r--java/res/values-ms/strings.xml2
-rw-r--r--java/res/values-nb/strings.xml2
-rw-r--r--java/res/values-nl/strings.xml2
-rw-r--r--java/res/values-pl/strings.xml2
-rw-r--r--java/res/values-pt-rPT/strings.xml2
-rw-r--r--java/res/values-pt/strings.xml2
-rw-r--r--java/res/values-rm/strings.xml4
-rw-r--r--java/res/values-ro/strings.xml2
-rw-r--r--java/res/values-ru/strings.xml2
-rw-r--r--java/res/values-sk/strings.xml2
-rw-r--r--java/res/values-sl/strings.xml2
-rw-r--r--java/res/values-sr/strings.xml2
-rw-r--r--java/res/values-sv/strings.xml2
-rw-r--r--java/res/values-sw/strings.xml2
-rw-r--r--java/res/values-sw600dp-land/setup-dimens.xml20
-rw-r--r--java/res/values-sw768dp-land/setup-dimens.xml20
-rw-r--r--java/res/values-th/strings.xml2
-rw-r--r--java/res/values-tl/strings.xml2
-rw-r--r--java/res/values-tr/strings.xml2
-rw-r--r--java/res/values-uk/strings.xml2
-rw-r--r--java/res/values-vi/strings.xml2
-rw-r--r--java/res/values-zh-rCN/strings.xml2
-rw-r--r--java/res/values-zh-rTW/strings.xml2
-rw-r--r--java/res/values-zu/strings.xml2
-rw-r--r--java/res/values/colors.xml5
-rw-r--r--java/res/values/setup-dimens.xml20
-rw-r--r--java/res/values/setup-styles.xml45
-rw-r--r--java/res/values/strings.xml51
-rw-r--r--java/res/xml-sw600dp/keys_pcqwerty3_right2.xml24
-rw-r--r--java/res/xml-v16/key_hindi1_shift.xml32
-rw-r--r--java/res/xml-v16/key_hindi3_right.xml36
-rw-r--r--java/res/xml-v16/key_hindi3_shift_left.xml34
-rw-r--r--java/res/xml-v16/key_hindi3_shift_right.xml34
-rw-r--r--java/res/xml-v16/keys_hindi1_left5.xml75
-rw-r--r--java/res/xml-v16/keys_hindi2_left5.xml59
-rw-r--r--java/res/xml-v16/keys_hindi3_left2.xml36
-rw-r--r--java/res/xml/key_hindi1_shift.xml34
-rw-r--r--java/res/xml/key_hindi3_right.xml38
-rw-r--r--java/res/xml/key_hindi3_shift_left.xml36
-rw-r--r--java/res/xml/key_hindi3_shift_right.xml36
-rw-r--r--java/res/xml/key_styles_enter.xml2
-rw-r--r--java/res/xml/keys_hindi1_left5.xml85
-rw-r--r--java/res/xml/keys_hindi2_left5.xml69
-rw-r--r--java/res/xml/keys_hindi3_left2.xml40
-rw-r--r--java/res/xml/keys_pcqwerty3_right2.xml14
-rw-r--r--java/res/xml/prefs.xml13
-rw-r--r--java/res/xml/row_symbols_shift4.xml8
-rw-r--r--java/res/xml/rowkeys_hindi1.xml61
-rw-r--r--java/res/xml/rowkeys_hindi2.xml36
-rw-r--r--java/res/xml/rowkeys_hindi3.xml48
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java17
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java86
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java4
-rw-r--r--java/src/com/android/inputmethod/compat/CompatUtils.java8
-rw-r--r--java/src/com/android/inputmethod/compat/IntentCompatUtils.java36
-rw-r--r--java/src/com/android/inputmethod/compat/TextViewCompatUtils.java44
-rw-r--r--java/src/com/android/inputmethod/compat/ViewCompatUtils.java68
-rw-r--r--java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java8
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java41
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java14
-rw-r--r--java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java1
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java980
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java1
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java81
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java10
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java14
-rw-r--r--java/src/com/android/inputmethod/latin/DebugSettings.java2
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java18
-rw-r--r--java/src/com/android/inputmethod/latin/InputTypeUtils.java9
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java82
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java4
-rw-r--r--java/src/com/android/inputmethod/latin/LocaleUtils.java5
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java14
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsFragment.java7
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictionary.java9
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java3
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java4
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FormatSpec.java14
-rw-r--r--java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java122
-rw-r--r--java/src/com/android/inputmethod/latin/setup/SetupActivity.java328
-rw-r--r--java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java56
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java4
-rw-r--r--java/src/com/android/inputmethod/research/LogUnit.java9
-rw-r--r--java/src/com/android/inputmethod/research/LoggingUtils.java38
-rw-r--r--java/src/com/android/inputmethod/research/MainLogBuffer.java59
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLog.java80
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java167
-rw-r--r--java/src/com/android/inputmethod/research/ResearchSettings.java61
-rw-r--r--java/src/com/android/inputmethod/research/Uploader.java180
-rw-r--r--java/src/com/android/inputmethod/research/UploaderService.java175
-rw-r--r--native/jni/src/char_utils.cpp6
-rw-r--r--native/jni/src/correction.cpp38
-rw-r--r--native/jni/src/correction.h2
-rw-r--r--native/jni/src/defines.h37
-rw-r--r--native/jni/src/proximity_info.cpp2
-rw-r--r--native/jni/src/proximity_info.h8
-rw-r--r--native/jni/src/proximity_info_state.cpp64
-rw-r--r--native/jni/src/proximity_info_state.h8
-rw-r--r--native/jni/src/proximity_info_state_utils.cpp20
-rw-r--r--native/jni/src/proximity_info_state_utils.h3
-rw-r--r--native/jni/src/proximity_info_utils.h2
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java25
-rw-r--r--tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java6
-rw-r--r--tools/maketext/res/values-ar/donottranslate-more-keys.xml26
-rw-r--r--tools/maketext/res/values-be/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-bg/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-cs/donottranslate-more-keys.xml4
-rw-r--r--tools/maketext/res/values-da/donottranslate-more-keys.xml4
-rw-r--r--tools/maketext/res/values-de/donottranslate-more-keys.xml4
-rw-r--r--tools/maketext/res/values-et/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-fa/donottranslate-more-keys.xml28
-rw-r--r--tools/maketext/res/values-hr/donottranslate-more-keys.xml4
-rw-r--r--tools/maketext/res/values-hu/donottranslate-more-keys.xml4
-rw-r--r--tools/maketext/res/values-is/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-iw/donottranslate-more-keys.xml24
-rw-r--r--tools/maketext/res/values-ka/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-lt/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-lv/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-mk/donottranslate-more-keys.xml16
-rw-r--r--tools/maketext/res/values-nb/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-nl/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-pl/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-ro/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-ru/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-sk/donottranslate-more-keys.xml4
-rw-r--r--tools/maketext/res/values-sl/donottranslate-more-keys.xml4
-rw-r--r--tools/maketext/res/values-sr/donottranslate-more-keys.xml18
-rw-r--r--tools/maketext/res/values-sv/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values-uk/donottranslate-more-keys.xml2
-rw-r--r--tools/maketext/res/values/donottranslate-more-keys.xml61
174 files changed, 3339 insertions, 2418 deletions
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index b88c18ee5..c05b318b9 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -24,6 +24,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:label="@string/aosp_android_keyboard_ime_name"
android:icon="@mipmap/ic_ime_settings"
@@ -50,12 +51,21 @@
<activity android:name=".setup.SetupActivity"
android:label="@string/aosp_android_keyboard_ime_name"
- android:icon="@mipmap/ic_ime_settings">
+ android:icon="@drawable/ic_setup_wizard">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <receiver android:name=".setup.LauncherIconVisibilityManager">
+ <intent-filter>
+ <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <action android:name="android.intent.action.USER_INITIALIZE" />
+ </intent-filter>
+ </receiver>
+
<activity android:name="SettingsActivity" android:label="@string/english_ime_settings"
android:uiOptions="splitActionBarWhenNarrow">
<intent-filter>
diff --git a/java/res/drawable-hdpi/ic_settings_language.png b/java/res/drawable-hdpi/ic_settings_language.png
new file mode 100644
index 000000000..f635b2e7a
--- /dev/null
+++ b/java/res/drawable-hdpi/ic_settings_language.png
Binary files differ
diff --git a/java/res/drawable-hdpi/ic_setup_wizard.png b/java/res/drawable-hdpi/ic_setup_wizard.png
new file mode 100644
index 000000000..38fca6d9d
--- /dev/null
+++ b/java/res/drawable-hdpi/ic_setup_wizard.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_settings_language.png b/java/res/drawable-mdpi/ic_settings_language.png
new file mode 100644
index 000000000..f8aca679b
--- /dev/null
+++ b/java/res/drawable-mdpi/ic_settings_language.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_setup_wizard.png b/java/res/drawable-mdpi/ic_setup_wizard.png
new file mode 100644
index 000000000..66e62b820
--- /dev/null
+++ b/java/res/drawable-mdpi/ic_setup_wizard.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_settings_language.png b/java/res/drawable-xhdpi/ic_settings_language.png
new file mode 100644
index 000000000..2c42db3aa
--- /dev/null
+++ b/java/res/drawable-xhdpi/ic_settings_language.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_setup_wizard.png b/java/res/drawable-xhdpi/ic_setup_wizard.png
new file mode 100644
index 000000000..53f70a617
--- /dev/null
+++ b/java/res/drawable-xhdpi/ic_setup_wizard.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_setup_wizard.png b/java/res/drawable-xxhdpi/ic_setup_wizard.png
new file mode 100644
index 000000000..6414b4f36
--- /dev/null
+++ b/java/res/drawable-xxhdpi/ic_setup_wizard.png
Binary files differ
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml
index 40eff3839..136e18cd5 100644
--- a/java/res/layout/input_view.xml
+++ b/java/res/layout/input_view.xml
@@ -43,8 +43,11 @@
android:layout_width="@dimen/suggestions_strip_padding"
android:layout_height="@dimen/suggestions_strip_height"
style="?attr/suggestionsStripBackgroundStyle" />
+ <!-- To ensure that key preview popup is correctly placed when the current system locale is
+ one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
<com.android.inputmethod.latin.suggestions.SuggestionStripView
android:id="@+id/suggestion_strip_view"
+ android:layoutDirection="ltr"
android:layout_weight="1.0"
android:layout_width="0dp"
android:layout_height="@dimen/suggestions_strip_height"
@@ -56,8 +59,11 @@
style="?attr/suggestionsStripBackgroundStyle" />
</LinearLayout>
+ <!-- To ensure that key preview popup is correctly placed when the current system locale is
+ one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
<com.android.inputmethod.keyboard.MainKeyboardView
android:id="@+id/keyboard_view"
+ android:layoutDirection="ltr"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
diff --git a/java/res/layout/setup_step.xml b/java/res/layout/setup_step.xml
new file mode 100644
index 000000000..26d7fe799
--- /dev/null
+++ b/java/res/layout/setup_step.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/setup_step_title"
+ style="@style/setupStepTitleStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp" />
+ <TextView
+ android:id="@+id/setup_step_instruction"
+ style="@style/setupStepInstructionStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="16dp"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp" />
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="2dp" />
+ <TextView
+ android:id="@+id/setup_step_action_label"
+ style="@style/setupStepActionLabelStyle"
+ android:gravity="center_vertical"
+ android:drawablePadding="12dp"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:clickable="true"
+ android:focusable="true"
+ android:paddingLeft="12dp"
+ android:paddingStart="12dp"
+ android:paddingRight="24dp"
+ android:paddingEnd="24dp" />
+</LinearLayout>
diff --git a/java/res/layout/setup_wizard.xml b/java/res/layout/setup_wizard.xml
new file mode 100644
index 000000000..acbbe30b3
--- /dev/null
+++ b/java/res/layout/setup_wizard.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/setup_background"
+ android:paddingLeft="@dimen/setup_horizontal_padding"
+ android:paddingRight="@dimen/setup_horizontal_padding"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp">
+ <TextView
+ android:id="@+id/setup_title"
+ style="@style/setupTitleStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true" />
+ <LinearLayout
+ android:id="@+id/setup_step_bullets"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/setup_title"
+ android:paddingTop="16dp"
+ android:orientation="horizontal">
+ <TextView
+ style="@style/setupStepBulletStyle"
+ android:text="@string/setup_step1_bullet" />
+ <TextView
+ style="@style/setupStepBulletStyle"
+ android:text="@string/setup_step2_bullet" />
+ <TextView
+ style="@style/setupStepBulletStyle"
+ android:text="@string/setup_step3_bullet" />
+ </LinearLayout>
+ <com.android.inputmethod.latin.setup.SetupStepIndicatorView
+ android:id="@+id/setup_step_indicator"
+ android:layout_width="match_parent"
+ android:layout_height="24dp"
+ android:layout_below="@id/setup_step_bullets" />
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/setup_step_indicator">
+ <include
+ android:id="@+id/setup_step1"
+ layout="@layout/setup_step" />
+ <include
+ android:id="@+id/setup_step2"
+ layout="@layout/setup_step" />
+ <include
+ android:id="@+id/setup_step3"
+ layout="@layout/setup_step" />
+ </FrameLayout>
+ </RelativeLayout>
+</ScrollView>
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 29d9d7785..4daf46568 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Moet hierdie lêer regtig vir <xliff:g id="LOCALE_NAME">%s</xliff:g> geïnstalleer word?"</string>
<string name="error" msgid="8940763624668513648">"Daar was \'n fout"</string>
<string name="button_default" msgid="3988017840431881491">"Verstek"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Taal en invoer"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Kies invoermetode"</string>
</resources>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index c9bc397de..d1fe341b9 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"እውን ይሄ ፋይል ለ<xliff:g id="LOCALE_NAME">%s</xliff:g> ይጫን?"</string>
<string name="error" msgid="8940763624668513648">"ስህተት ተከስቶ ነበር"</string>
<string name="button_default" msgid="3988017840431881491">"ነባሪ"</string>
+ <string name="language_settings" msgid="1671153053201809031">"ቋንቋ እና ግቤት"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"የግቤት ስልት ይምረጡ"</string>
</resources>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 95fd99f85..bca3c2aa3 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"هل تريد حقًا تثبيت هذا الملف للغة <xliff:g id="LOCALE_NAME">%s</xliff:g>؟"</string>
<string name="error" msgid="8940763624668513648">"حدث خطأ"</string>
<string name="button_default" msgid="3988017840431881491">"الافتراضية"</string>
+ <string name="language_settings" msgid="1671153053201809031">"اللغة والإدخال"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"اختيار أسلوب الإدخال"</string>
</resources>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index 6de0e0bda..56382e42e 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Сапраўды ўсталяваць гэты файл на мове: <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Была памылка"</string>
<string name="button_default" msgid="3988017840431881491">"Па змаўчанні"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Мова і ўвод"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Выберыце метад уводу"</string>
</resources>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index c971d7b73..3ffebea48 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Наистина ли да се инсталира този файл за <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Възникна грешка"</string>
<string name="button_default" msgid="3988017840431881491">"Стандартни"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Език и въвеждане"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Избор на метод на въвеждане"</string>
</resources>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 23dcda9d3..26527381f 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Realment vols instal·lar aquest fitxer per a <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"S\'ha produït un error"</string>
<string name="button_default" msgid="3988017840431881491">"Predeterminat"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Idioma i introducció"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Selecció de mètodes d\'introducció"</string>
</resources>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 5625c74fb..7e12f06d8 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Chcete nainstalovat tento soubor pro jazyk <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Došlo k chybě"</string>
<string name="button_default" msgid="3988017840431881491">"Výchozí"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Jazyk a zadávání"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Výběr metody zadávání dat"</string>
</resources>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 6c7936f1d..3ea4aaaef 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Er du klar til at installere denne fil til <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Der opstod en fejl"</string>
<string name="button_default" msgid="3988017840431881491">"Standard"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Sprog og input"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Vælg inputmetode"</string>
</resources>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 18fb51bb7..a50cdf0d0 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Möchten Sie diese Datei für <xliff:g id="LOCALE_NAME">%s</xliff:g> installieren?"</string>
<string name="error" msgid="8940763624668513648">"Es ist ein Fehler aufgetreten"</string>
<string name="button_default" msgid="3988017840431881491">"Standard"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Sprache &amp; Eingabe"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Eingabemethode wählen"</string>
</resources>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index b6d937937..153dbbbf4 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Να εγκατασταθεί όντως αυτό το αρχείο για <xliff:g id="LOCALE_NAME">%s</xliff:g>;"</string>
<string name="error" msgid="8940763624668513648">"Παρουσιάστηκε σφάλμα."</string>
<string name="button_default" msgid="3988017840431881491">"Προεπιλογή"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Γλώσσα και εισαγωγή"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Επιλογή μεθόδου εισαγωγής"</string>
</resources>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 01ead1bae..5fbbdf667 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Really install this file for <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"There was an error"</string>
<string name="button_default" msgid="3988017840431881491">"Default"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Language &amp; input"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Choose input method"</string>
</resources>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 53d759844..71841f805 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"¿Realmente quieres instalar este archivo para <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Se produjo un error."</string>
<string name="button_default" msgid="3988017840431881491">"Predeterminado"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Teclado e idioma"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Seleccionar método de entrada"</string>
</resources>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 6f54dd6d0..9b31884a2 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"¿Seguro que quieres instalar este archivo para <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Se ha producido un error"</string>
<string name="button_default" msgid="3988017840431881491">"Predeterminado"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Idioma y entrada de texto"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Selecciona un método de entrada"</string>
</resources>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index 9cf6a9ff3..3364abe5e 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Kas soovite tõesti installida faili lokaadile <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Ilmnes viga"</string>
<string name="button_default" msgid="3988017840431881491">"Vaikeväärtus"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Keeled ja sisestamine"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Valige sisestusmeetod"</string>
</resources>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 682105894..54ba41256 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -161,4 +161,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"این فایل واقعاً برای <xliff:g id="LOCALE_NAME">%s</xliff:g> نصب شود؟"</string>
<string name="error" msgid="8940763624668513648">"خطایی روی داد"</string>
<string name="button_default" msgid="3988017840431881491">"پیش‌فرض"</string>
+ <string name="language_settings" msgid="1671153053201809031">"زبان و ورودی"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"انتخاب روش ورودی"</string>
</resources>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 4e55232db..2d754023c 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Haluatko asentaa tämä tiedoston kielelle <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Tapahtui virhe"</string>
<string name="button_default" msgid="3988017840431881491">"Oletusarvot"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Kieli ja syöttötapa"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Valitse syöttötapa"</string>
</resources>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index c552a7f6c..f327f90f9 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Installer ce fichier pour la langue \"<xliff:g id="LOCALE_NAME">%s</xliff:g>\" ?"</string>
<string name="error" msgid="8940763624668513648">"Une erreur s\'est produite"</string>
<string name="button_default" msgid="3988017840431881491">"Par défaut"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Langue et saisie"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Sélectionnez le mode de saisie"</string>
</resources>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 72320ea09..e52143dc6 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"<xliff:g id="LOCALE_NAME">%s</xliff:g> के लिए वास्तव में यह फ़ाइल इंस्टॉल करें?"</string>
<string name="error" msgid="8940763624668513648">"कोई त्रुटि हुई थी"</string>
<string name="button_default" msgid="3988017840431881491">"डिफ़ॉल्ट"</string>
+ <string name="language_settings" msgid="1671153053201809031">"भाषा और इनपुट"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"इनपुट पद्धति चुनें"</string>
</resources>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 8432ed54f..564d48f14 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Želite li doista instalirati ovu datoteku za <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Došlo je do pogreške"</string>
<string name="button_default" msgid="3988017840431881491">"Zadano"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Jezik i unos"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Odabir načina unosa"</string>
</resources>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index eb4bde297..047a31a6c 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Valóban telepíti ezt a fájlt <xliff:g id="LOCALE_NAME">%s</xliff:g> nyelvhez?"</string>
<string name="error" msgid="8940763624668513648">"Hiba történt."</string>
<string name="button_default" msgid="3988017840431881491">"Alapértelmezett"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Nyelv és bevitel"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Beviteli mód kiválasztása"</string>
</resources>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 646c3aaa2..ba9a7da4c 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Yakin ingin memasang file ini untuk <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Terjadi kesalahan"</string>
<string name="button_default" msgid="3988017840431881491">"Default"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Bahasa &amp; masukan"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Pilih metode masukan"</string>
</resources>
diff --git a/java/res/values-is/strings.xml b/java/res/values-is/strings.xml
deleted file mode 100644
index 678d3cfc3..000000000
--- a/java/res/values-is/strings.xml
+++ /dev/null
@@ -1,292 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) -->
- <skip />
- <!-- no translation found for english_ime_input_options (3909945612939668554) -->
- <skip />
- <!-- no translation found for english_ime_research_log (8492602295696577851) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
- <skip />
- <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
- <skip />
- <!-- no translation found for sound_on_keypress (6093592297198243644) -->
- <skip />
- <!-- no translation found for popup_on_keypress (123894815723512944) -->
- <skip />
- <!-- no translation found for general_category (1859088467017573195) -->
- <skip />
- <!-- no translation found for correction_category (2236750915056607613) -->
- <skip />
- <!-- no translation found for gesture_typing_category (497263612130532630) -->
- <skip />
- <!-- no translation found for misc_category (6894192814868233453) -->
- <skip />
- <!-- no translation found for advanced_settings (362895144495591463) -->
- <skip />
- <!-- no translation found for advanced_settings_summary (4487980456152830271) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
- <skip />
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
- <skip />
- <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
- <skip />
- <!-- no translation found for use_contacts_dict (4435317977804180815) -->
- <skip />
- <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
- <skip />
- <!-- no translation found for use_double_space_period (8781529969425082860) -->
- <skip />
- <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
- <skip />
- <!-- no translation found for auto_cap (1719746674854628252) -->
- <skip />
- <!-- no translation found for auto_cap_summary (7934452761022946874) -->
- <skip />
- <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
- <skip />
- <!-- no translation found for main_dictionary (4798763781818361168) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
- <skip />
- <!-- no translation found for auto_correction (7630720885194996950) -->
- <skip />
- <!-- no translation found for auto_correction_summary (5625751551134658006) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_aggeressive (3524029103734923819) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
- <skip />
- <!-- no translation found for bigram_prediction (1084449187723948550) -->
- <skip />
- <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
- <skip />
- <!-- no translation found for gesture_input (826951152254563827) -->
- <skip />
- <!-- no translation found for gesture_input_summary (9180350639305731231) -->
- <skip />
- <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
- <skip />
- <!-- no translation found for added_word (8993883354622484372) -->
- <skip />
- <string name="label_go_key" msgid="1635148082137219148">"Áfram"</string>
- <string name="label_next_key" msgid="362972844525672568">"Næsta"</string>
- <string name="label_previous_key" msgid="1211868118071386787">"Fyrra"</string>
- <string name="label_done_key" msgid="2441578748772529288">"Lokið"</string>
- <string name="label_send_key" msgid="2815056534433717444">"Senda"</string>
- <!-- no translation found for label_pause_key (181098308428035340) -->
- <skip />
- <!-- no translation found for label_wait_key (6402152600878093134) -->
- <skip />
- <!-- no translation found for spoken_use_headphones (896961781287283493) -->
- <skip />
- <!-- no translation found for spoken_current_text_is (2485723011272583845) -->
- <skip />
- <!-- no translation found for spoken_no_text_entered (7479685225597344496) -->
- <skip />
- <!-- no translation found for spoken_description_unknown (3197434010402179157) -->
- <skip />
- <!-- no translation found for spoken_description_shift (244197883292549308) -->
- <skip />
- <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) -->
- <skip />
- <!-- no translation found for spoken_description_caps_lock (3276478269526304432) -->
- <skip />
- <!-- no translation found for spoken_description_delete (8740376944276199801) -->
- <skip />
- <!-- no translation found for spoken_description_to_symbol (5486340107500448969) -->
- <skip />
- <!-- no translation found for spoken_description_to_alpha (23129338819771807) -->
- <skip />
- <!-- no translation found for spoken_description_to_numeric (591752092685161732) -->
- <skip />
- <!-- no translation found for spoken_description_settings (4627462689603838099) -->
- <skip />
- <!-- no translation found for spoken_description_tab (2667716002663482248) -->
- <skip />
- <!-- no translation found for spoken_description_space (2582521050049860859) -->
- <skip />
- <!-- no translation found for spoken_description_mic (615536748882611950) -->
- <skip />
- <!-- no translation found for spoken_description_smiley (2256309826200113918) -->
- <skip />
- <!-- no translation found for spoken_description_return (8178083177238315647) -->
- <skip />
- <!-- no translation found for spoken_description_search (1247236163755920808) -->
- <skip />
- <!-- no translation found for spoken_description_dot (40711082435231673) -->
- <skip />
- <!-- no translation found for spoken_description_language_switch (5507091328222331316) -->
- <skip />
- <!-- no translation found for spoken_description_action_next (8636078276664150324) -->
- <skip />
- <!-- no translation found for spoken_description_action_previous (800872415009336208) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) -->
- <skip />
- <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) -->
- <skip />
- <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone (6520207943132026264) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) -->
- <skip />
- <!-- no translation found for voice_input (3583258583521397548) -->
- <skip />
- <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) -->
- <skip />
- <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) -->
- <skip />
- <!-- no translation found for voice_input_modes_off (3745699748218082014) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_off (63875609591897607) -->
- <skip />
- <!-- no translation found for configure_input_method (373356270290742459) -->
- <skip />
- <!-- no translation found for language_selection_title (1651299598555326750) -->
- <skip />
- <!-- no translation found for select_language (3693815588777926848) -->
- <skip />
- <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
- <skip />
- <!-- no translation found for has_dictionary (6071847973466625007) -->
- <skip />
- <!-- no translation found for prefs_enable_log (6620424505072963557) -->
- <skip />
- <!-- no translation found for prefs_description_log (5827825607258246003) -->
- <skip />
- <!-- no translation found for keyboard_layout (8451164783510487501) -->
- <skip />
- <!-- no translation found for subtype_en_GB (88170601942311355) -->
- <skip />
- <!-- no translation found for subtype_en_US (6160452336634534239) -->
- <skip />
- <!-- no translation found for subtype_es_US (5583145191430180200) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_GB (2179097748724725906) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_US (1362581347576714579) -->
- <skip />
- <!-- no translation found for subtype_with_layout_es_US (6261791057007890189) -->
- <skip />
- <!-- no translation found for subtype_no_language (141420857808801746) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwerty (2956121451616633133) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwertz (1177848172397202890) -->
- <skip />
- <!-- no translation found for subtype_no_language_azerty (8721460968141187394) -->
- <skip />
- <!-- no translation found for subtype_no_language_dvorak (3122976737669823935) -->
- <skip />
- <!-- no translation found for subtype_no_language_colemak (4205992994906097244) -->
- <skip />
- <!-- no translation found for subtype_no_language_pcqwerty (8840928374394180189) -->
- <skip />
- <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
- <skip />
- <!-- no translation found for add_style (6163126614514489951) -->
- <skip />
- <!-- no translation found for add (8299699805688017798) -->
- <skip />
- <!-- no translation found for remove (4486081658752944606) -->
- <skip />
- <!-- no translation found for save (7646738597196767214) -->
- <skip />
- <!-- no translation found for subtype_locale (8576443440738143764) -->
- <skip />
- <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
- <skip />
- <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
- <skip />
- <!-- no translation found for enable (5031294444630523247) -->
- <skip />
- <!-- no translation found for not_now (6172462888202790482) -->
- <skip />
- <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
- <skip />
- <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
- <skip />
- <!-- no translation found for prefs_key_longpress_timeout_settings (1881822418815012326) -->
- <skip />
- <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
- <skip />
- <!-- no translation found for prefs_keypress_sound_volume_settings (5875933757082305040) -->
- <skip />
- <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
- <skip />
- <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
- <skip />
- <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
- <skip />
- <!-- no translation found for read_external_dictionary_confirm_install_message (6898610163768980870) -->
- <skip />
- <!-- no translation found for error (8940763624668513648) -->
- <skip />
- <!-- no translation found for button_default (3988017840431881491) -->
- <skip />
-</resources>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index e353d8e9b..56acdf8ce 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Installare questo file per <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Si è verificato un errore"</string>
<string name="button_default" msgid="3988017840431881491">"Predefinito"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Lingua e input"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Scegli il metodo di immissione"</string>
</resources>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index e537efba9..7c55ab569 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"האם באמת להתקין את הקובץ הזה עבור <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"אירעה שגיאה"</string>
<string name="button_default" msgid="3988017840431881491">"ברירת מחדל"</string>
+ <string name="language_settings" msgid="1671153053201809031">"שפה וקלט"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"בחירת שיטת קלט"</string>
</resources>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 9aedb6d9a..9328f0184 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"この<xliff:g id="LOCALE_NAME">%s</xliff:g>のファイルをインストールしてもよろしいですか?"</string>
<string name="error" msgid="8940763624668513648">"エラーが発生しました"</string>
<string name="button_default" msgid="3988017840431881491">"デフォルト"</string>
+ <string name="language_settings" msgid="1671153053201809031">"言語と入力"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"入力方法の選択"</string>
</resources>
diff --git a/java/res/values-ka/strings.xml b/java/res/values-ka/strings.xml
deleted file mode 100644
index 4c0f17c86..000000000
--- a/java/res/values-ka/strings.xml
+++ /dev/null
@@ -1,292 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) -->
- <skip />
- <!-- no translation found for english_ime_input_options (3909945612939668554) -->
- <skip />
- <!-- no translation found for english_ime_research_log (8492602295696577851) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
- <skip />
- <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
- <skip />
- <!-- no translation found for sound_on_keypress (6093592297198243644) -->
- <skip />
- <!-- no translation found for popup_on_keypress (123894815723512944) -->
- <skip />
- <!-- no translation found for general_category (1859088467017573195) -->
- <skip />
- <!-- no translation found for correction_category (2236750915056607613) -->
- <skip />
- <!-- no translation found for gesture_typing_category (497263612130532630) -->
- <skip />
- <!-- no translation found for misc_category (6894192814868233453) -->
- <skip />
- <!-- no translation found for advanced_settings (362895144495591463) -->
- <skip />
- <!-- no translation found for advanced_settings_summary (4487980456152830271) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
- <skip />
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
- <skip />
- <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
- <skip />
- <!-- no translation found for use_contacts_dict (4435317977804180815) -->
- <skip />
- <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
- <skip />
- <!-- no translation found for use_double_space_period (8781529969425082860) -->
- <skip />
- <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
- <skip />
- <!-- no translation found for auto_cap (1719746674854628252) -->
- <skip />
- <!-- no translation found for auto_cap_summary (7934452761022946874) -->
- <skip />
- <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
- <skip />
- <!-- no translation found for main_dictionary (4798763781818361168) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
- <skip />
- <!-- no translation found for auto_correction (7630720885194996950) -->
- <skip />
- <!-- no translation found for auto_correction_summary (5625751551134658006) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_aggeressive (3524029103734923819) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
- <skip />
- <!-- no translation found for bigram_prediction (1084449187723948550) -->
- <skip />
- <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
- <skip />
- <!-- no translation found for gesture_input (826951152254563827) -->
- <skip />
- <!-- no translation found for gesture_input_summary (9180350639305731231) -->
- <skip />
- <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
- <skip />
- <!-- no translation found for added_word (8993883354622484372) -->
- <skip />
- <string name="label_go_key" msgid="1635148082137219148">"გადასვლა"</string>
- <string name="label_next_key" msgid="362972844525672568">"შემდეგი"</string>
- <string name="label_previous_key" msgid="1211868118071386787">"წინა"</string>
- <string name="label_done_key" msgid="2441578748772529288">"შესრულებულია"</string>
- <string name="label_send_key" msgid="2815056534433717444">"გაგზავნა"</string>
- <!-- no translation found for label_pause_key (181098308428035340) -->
- <skip />
- <!-- no translation found for label_wait_key (6402152600878093134) -->
- <skip />
- <!-- no translation found for spoken_use_headphones (896961781287283493) -->
- <skip />
- <!-- no translation found for spoken_current_text_is (2485723011272583845) -->
- <skip />
- <!-- no translation found for spoken_no_text_entered (7479685225597344496) -->
- <skip />
- <!-- no translation found for spoken_description_unknown (3197434010402179157) -->
- <skip />
- <!-- no translation found for spoken_description_shift (244197883292549308) -->
- <skip />
- <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) -->
- <skip />
- <!-- no translation found for spoken_description_caps_lock (3276478269526304432) -->
- <skip />
- <!-- no translation found for spoken_description_delete (8740376944276199801) -->
- <skip />
- <!-- no translation found for spoken_description_to_symbol (5486340107500448969) -->
- <skip />
- <!-- no translation found for spoken_description_to_alpha (23129338819771807) -->
- <skip />
- <!-- no translation found for spoken_description_to_numeric (591752092685161732) -->
- <skip />
- <!-- no translation found for spoken_description_settings (4627462689603838099) -->
- <skip />
- <!-- no translation found for spoken_description_tab (2667716002663482248) -->
- <skip />
- <!-- no translation found for spoken_description_space (2582521050049860859) -->
- <skip />
- <!-- no translation found for spoken_description_mic (615536748882611950) -->
- <skip />
- <!-- no translation found for spoken_description_smiley (2256309826200113918) -->
- <skip />
- <!-- no translation found for spoken_description_return (8178083177238315647) -->
- <skip />
- <!-- no translation found for spoken_description_search (1247236163755920808) -->
- <skip />
- <!-- no translation found for spoken_description_dot (40711082435231673) -->
- <skip />
- <!-- no translation found for spoken_description_language_switch (5507091328222331316) -->
- <skip />
- <!-- no translation found for spoken_description_action_next (8636078276664150324) -->
- <skip />
- <!-- no translation found for spoken_description_action_previous (800872415009336208) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) -->
- <skip />
- <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) -->
- <skip />
- <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone (6520207943132026264) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) -->
- <skip />
- <!-- no translation found for voice_input (3583258583521397548) -->
- <skip />
- <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) -->
- <skip />
- <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) -->
- <skip />
- <!-- no translation found for voice_input_modes_off (3745699748218082014) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_off (63875609591897607) -->
- <skip />
- <!-- no translation found for configure_input_method (373356270290742459) -->
- <skip />
- <!-- no translation found for language_selection_title (1651299598555326750) -->
- <skip />
- <!-- no translation found for select_language (3693815588777926848) -->
- <skip />
- <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
- <skip />
- <!-- no translation found for has_dictionary (6071847973466625007) -->
- <skip />
- <!-- no translation found for prefs_enable_log (6620424505072963557) -->
- <skip />
- <!-- no translation found for prefs_description_log (5827825607258246003) -->
- <skip />
- <!-- no translation found for keyboard_layout (8451164783510487501) -->
- <skip />
- <!-- no translation found for subtype_en_GB (88170601942311355) -->
- <skip />
- <!-- no translation found for subtype_en_US (6160452336634534239) -->
- <skip />
- <!-- no translation found for subtype_es_US (5583145191430180200) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_GB (2179097748724725906) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_US (1362581347576714579) -->
- <skip />
- <!-- no translation found for subtype_with_layout_es_US (6261791057007890189) -->
- <skip />
- <!-- no translation found for subtype_no_language (141420857808801746) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwerty (2956121451616633133) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwertz (1177848172397202890) -->
- <skip />
- <!-- no translation found for subtype_no_language_azerty (8721460968141187394) -->
- <skip />
- <!-- no translation found for subtype_no_language_dvorak (3122976737669823935) -->
- <skip />
- <!-- no translation found for subtype_no_language_colemak (4205992994906097244) -->
- <skip />
- <!-- no translation found for subtype_no_language_pcqwerty (8840928374394180189) -->
- <skip />
- <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
- <skip />
- <!-- no translation found for add_style (6163126614514489951) -->
- <skip />
- <!-- no translation found for add (8299699805688017798) -->
- <skip />
- <!-- no translation found for remove (4486081658752944606) -->
- <skip />
- <!-- no translation found for save (7646738597196767214) -->
- <skip />
- <!-- no translation found for subtype_locale (8576443440738143764) -->
- <skip />
- <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
- <skip />
- <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
- <skip />
- <!-- no translation found for enable (5031294444630523247) -->
- <skip />
- <!-- no translation found for not_now (6172462888202790482) -->
- <skip />
- <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
- <skip />
- <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
- <skip />
- <!-- no translation found for prefs_key_longpress_timeout_settings (1881822418815012326) -->
- <skip />
- <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
- <skip />
- <!-- no translation found for prefs_keypress_sound_volume_settings (5875933757082305040) -->
- <skip />
- <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
- <skip />
- <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
- <skip />
- <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
- <skip />
- <!-- no translation found for read_external_dictionary_confirm_install_message (6898610163768980870) -->
- <skip />
- <!-- no translation found for error (8940763624668513648) -->
- <skip />
- <!-- no translation found for button_default (3988017840431881491) -->
- <skip />
-</resources>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 13fb4cf24..f6086eed5 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"이 파일을 <xliff:g id="LOCALE_NAME">%s</xliff:g>(으)로 설치하시겠습니까?"</string>
<string name="error" msgid="8940763624668513648">"오류 발생"</string>
<string name="button_default" msgid="3988017840431881491">"기본값"</string>
+ <string name="language_settings" msgid="1671153053201809031">"언어 및 키보드"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"입력 방법 선택"</string>
</resources>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index b023a17f5..a815003b2 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Ar tikrai įdiegti šį failą <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Įvyko klaida"</string>
<string name="button_default" msgid="3988017840431881491">"Numatytieji"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Kalba ir įvestis"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Pasirinkite įvesties metodą"</string>
</resources>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 23be520a4..6a408cfce 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Vai instalēt šo failu šādai valodai: <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Radās kļūda"</string>
<string name="button_default" msgid="3988017840431881491">"Noklusējums"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Valoda un ievade"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Ievades metodes izvēle"</string>
</resources>
diff --git a/java/res/values-mk/strings.xml b/java/res/values-mk/strings.xml
deleted file mode 100644
index e7189d5c2..000000000
--- a/java/res/values-mk/strings.xml
+++ /dev/null
@@ -1,292 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) -->
- <skip />
- <!-- no translation found for english_ime_input_options (3909945612939668554) -->
- <skip />
- <!-- no translation found for english_ime_research_log (8492602295696577851) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
- <skip />
- <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
- <skip />
- <!-- no translation found for sound_on_keypress (6093592297198243644) -->
- <skip />
- <!-- no translation found for popup_on_keypress (123894815723512944) -->
- <skip />
- <!-- no translation found for general_category (1859088467017573195) -->
- <skip />
- <!-- no translation found for correction_category (2236750915056607613) -->
- <skip />
- <!-- no translation found for gesture_typing_category (497263612130532630) -->
- <skip />
- <!-- no translation found for misc_category (6894192814868233453) -->
- <skip />
- <!-- no translation found for advanced_settings (362895144495591463) -->
- <skip />
- <!-- no translation found for advanced_settings_summary (4487980456152830271) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
- <skip />
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
- <skip />
- <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
- <skip />
- <!-- no translation found for use_contacts_dict (4435317977804180815) -->
- <skip />
- <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
- <skip />
- <!-- no translation found for use_double_space_period (8781529969425082860) -->
- <skip />
- <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
- <skip />
- <!-- no translation found for auto_cap (1719746674854628252) -->
- <skip />
- <!-- no translation found for auto_cap_summary (7934452761022946874) -->
- <skip />
- <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
- <skip />
- <!-- no translation found for main_dictionary (4798763781818361168) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
- <skip />
- <!-- no translation found for auto_correction (7630720885194996950) -->
- <skip />
- <!-- no translation found for auto_correction_summary (5625751551134658006) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_aggeressive (3524029103734923819) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
- <skip />
- <!-- no translation found for bigram_prediction (1084449187723948550) -->
- <skip />
- <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
- <skip />
- <!-- no translation found for gesture_input (826951152254563827) -->
- <skip />
- <!-- no translation found for gesture_input_summary (9180350639305731231) -->
- <skip />
- <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
- <skip />
- <!-- no translation found for added_word (8993883354622484372) -->
- <skip />
- <string name="label_go_key" msgid="1635148082137219148">"Оди"</string>
- <string name="label_next_key" msgid="362972844525672568">"Следно"</string>
- <string name="label_previous_key" msgid="1211868118071386787">"Претходно"</string>
- <string name="label_done_key" msgid="2441578748772529288">"Готово"</string>
- <string name="label_send_key" msgid="2815056534433717444">"Испрати"</string>
- <!-- no translation found for label_pause_key (181098308428035340) -->
- <skip />
- <!-- no translation found for label_wait_key (6402152600878093134) -->
- <skip />
- <!-- no translation found for spoken_use_headphones (896961781287283493) -->
- <skip />
- <!-- no translation found for spoken_current_text_is (2485723011272583845) -->
- <skip />
- <!-- no translation found for spoken_no_text_entered (7479685225597344496) -->
- <skip />
- <!-- no translation found for spoken_description_unknown (3197434010402179157) -->
- <skip />
- <!-- no translation found for spoken_description_shift (244197883292549308) -->
- <skip />
- <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) -->
- <skip />
- <!-- no translation found for spoken_description_caps_lock (3276478269526304432) -->
- <skip />
- <!-- no translation found for spoken_description_delete (8740376944276199801) -->
- <skip />
- <!-- no translation found for spoken_description_to_symbol (5486340107500448969) -->
- <skip />
- <!-- no translation found for spoken_description_to_alpha (23129338819771807) -->
- <skip />
- <!-- no translation found for spoken_description_to_numeric (591752092685161732) -->
- <skip />
- <!-- no translation found for spoken_description_settings (4627462689603838099) -->
- <skip />
- <!-- no translation found for spoken_description_tab (2667716002663482248) -->
- <skip />
- <!-- no translation found for spoken_description_space (2582521050049860859) -->
- <skip />
- <!-- no translation found for spoken_description_mic (615536748882611950) -->
- <skip />
- <!-- no translation found for spoken_description_smiley (2256309826200113918) -->
- <skip />
- <!-- no translation found for spoken_description_return (8178083177238315647) -->
- <skip />
- <!-- no translation found for spoken_description_search (1247236163755920808) -->
- <skip />
- <!-- no translation found for spoken_description_dot (40711082435231673) -->
- <skip />
- <!-- no translation found for spoken_description_language_switch (5507091328222331316) -->
- <skip />
- <!-- no translation found for spoken_description_action_next (8636078276664150324) -->
- <skip />
- <!-- no translation found for spoken_description_action_previous (800872415009336208) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) -->
- <skip />
- <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) -->
- <skip />
- <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone (6520207943132026264) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) -->
- <skip />
- <!-- no translation found for voice_input (3583258583521397548) -->
- <skip />
- <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) -->
- <skip />
- <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) -->
- <skip />
- <!-- no translation found for voice_input_modes_off (3745699748218082014) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_off (63875609591897607) -->
- <skip />
- <!-- no translation found for configure_input_method (373356270290742459) -->
- <skip />
- <!-- no translation found for language_selection_title (1651299598555326750) -->
- <skip />
- <!-- no translation found for select_language (3693815588777926848) -->
- <skip />
- <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
- <skip />
- <!-- no translation found for has_dictionary (6071847973466625007) -->
- <skip />
- <!-- no translation found for prefs_enable_log (6620424505072963557) -->
- <skip />
- <!-- no translation found for prefs_description_log (5827825607258246003) -->
- <skip />
- <!-- no translation found for keyboard_layout (8451164783510487501) -->
- <skip />
- <!-- no translation found for subtype_en_GB (88170601942311355) -->
- <skip />
- <!-- no translation found for subtype_en_US (6160452336634534239) -->
- <skip />
- <!-- no translation found for subtype_es_US (5583145191430180200) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_GB (2179097748724725906) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_US (1362581347576714579) -->
- <skip />
- <!-- no translation found for subtype_with_layout_es_US (6261791057007890189) -->
- <skip />
- <!-- no translation found for subtype_no_language (141420857808801746) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwerty (2956121451616633133) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwertz (1177848172397202890) -->
- <skip />
- <!-- no translation found for subtype_no_language_azerty (8721460968141187394) -->
- <skip />
- <!-- no translation found for subtype_no_language_dvorak (3122976737669823935) -->
- <skip />
- <!-- no translation found for subtype_no_language_colemak (4205992994906097244) -->
- <skip />
- <!-- no translation found for subtype_no_language_pcqwerty (8840928374394180189) -->
- <skip />
- <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
- <skip />
- <!-- no translation found for add_style (6163126614514489951) -->
- <skip />
- <!-- no translation found for add (8299699805688017798) -->
- <skip />
- <!-- no translation found for remove (4486081658752944606) -->
- <skip />
- <!-- no translation found for save (7646738597196767214) -->
- <skip />
- <!-- no translation found for subtype_locale (8576443440738143764) -->
- <skip />
- <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
- <skip />
- <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
- <skip />
- <!-- no translation found for enable (5031294444630523247) -->
- <skip />
- <!-- no translation found for not_now (6172462888202790482) -->
- <skip />
- <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
- <skip />
- <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
- <skip />
- <!-- no translation found for prefs_key_longpress_timeout_settings (1881822418815012326) -->
- <skip />
- <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
- <skip />
- <!-- no translation found for prefs_keypress_sound_volume_settings (5875933757082305040) -->
- <skip />
- <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
- <skip />
- <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
- <skip />
- <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
- <skip />
- <!-- no translation found for read_external_dictionary_confirm_install_message (6898610163768980870) -->
- <skip />
- <!-- no translation found for error (8940763624668513648) -->
- <skip />
- <!-- no translation found for button_default (3988017840431881491) -->
- <skip />
-</resources>
diff --git a/java/res/values-mn/strings.xml b/java/res/values-mn/strings.xml
deleted file mode 100644
index 0372701db..000000000
--- a/java/res/values-mn/strings.xml
+++ /dev/null
@@ -1,292 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/*
-**
-** Copyright 2008, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) -->
- <skip />
- <!-- no translation found for english_ime_input_options (3909945612939668554) -->
- <skip />
- <!-- no translation found for english_ime_research_log (8492602295696577851) -->
- <skip />
- <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
- <skip />
- <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
- <skip />
- <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
- <skip />
- <!-- no translation found for sound_on_keypress (6093592297198243644) -->
- <skip />
- <!-- no translation found for popup_on_keypress (123894815723512944) -->
- <skip />
- <!-- no translation found for general_category (1859088467017573195) -->
- <skip />
- <!-- no translation found for correction_category (2236750915056607613) -->
- <skip />
- <!-- no translation found for gesture_typing_category (497263612130532630) -->
- <skip />
- <!-- no translation found for misc_category (6894192814868233453) -->
- <skip />
- <!-- no translation found for advanced_settings (362895144495591463) -->
- <skip />
- <!-- no translation found for advanced_settings_summary (4487980456152830271) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
- <skip />
- <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
- <skip />
- <!-- no translation found for show_language_switch_key (5915478828318774384) -->
- <skip />
- <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
- <skip />
- <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
- <skip />
- <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
- <skip />
- <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
- <skip />
- <!-- no translation found for use_contacts_dict (4435317977804180815) -->
- <skip />
- <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
- <skip />
- <!-- no translation found for use_double_space_period (8781529969425082860) -->
- <skip />
- <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
- <skip />
- <!-- no translation found for auto_cap (1719746674854628252) -->
- <skip />
- <!-- no translation found for auto_cap_summary (7934452761022946874) -->
- <skip />
- <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
- <skip />
- <!-- no translation found for main_dictionary (4798763781818361168) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
- <skip />
- <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
- <skip />
- <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
- <skip />
- <!-- no translation found for auto_correction (7630720885194996950) -->
- <skip />
- <!-- no translation found for auto_correction_summary (5625751551134658006) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_aggeressive (3524029103734923819) -->
- <skip />
- <!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
- <skip />
- <!-- no translation found for bigram_prediction (1084449187723948550) -->
- <skip />
- <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
- <skip />
- <!-- no translation found for gesture_input (826951152254563827) -->
- <skip />
- <!-- no translation found for gesture_input_summary (9180350639305731231) -->
- <skip />
- <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
- <skip />
- <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
- <skip />
- <!-- no translation found for added_word (8993883354622484372) -->
- <skip />
- <string name="label_go_key" msgid="1635148082137219148">"Очих"</string>
- <string name="label_next_key" msgid="362972844525672568">"Дараагийн"</string>
- <string name="label_previous_key" msgid="1211868118071386787">"Өмнөх"</string>
- <string name="label_done_key" msgid="2441578748772529288">"Хийгдлээ"</string>
- <string name="label_send_key" msgid="2815056534433717444">"Илгээх"</string>
- <!-- no translation found for label_pause_key (181098308428035340) -->
- <skip />
- <!-- no translation found for label_wait_key (6402152600878093134) -->
- <skip />
- <!-- no translation found for spoken_use_headphones (896961781287283493) -->
- <skip />
- <!-- no translation found for spoken_current_text_is (2485723011272583845) -->
- <skip />
- <!-- no translation found for spoken_no_text_entered (7479685225597344496) -->
- <skip />
- <!-- no translation found for spoken_description_unknown (3197434010402179157) -->
- <skip />
- <!-- no translation found for spoken_description_shift (244197883292549308) -->
- <skip />
- <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) -->
- <skip />
- <!-- no translation found for spoken_description_caps_lock (3276478269526304432) -->
- <skip />
- <!-- no translation found for spoken_description_delete (8740376944276199801) -->
- <skip />
- <!-- no translation found for spoken_description_to_symbol (5486340107500448969) -->
- <skip />
- <!-- no translation found for spoken_description_to_alpha (23129338819771807) -->
- <skip />
- <!-- no translation found for spoken_description_to_numeric (591752092685161732) -->
- <skip />
- <!-- no translation found for spoken_description_settings (4627462689603838099) -->
- <skip />
- <!-- no translation found for spoken_description_tab (2667716002663482248) -->
- <skip />
- <!-- no translation found for spoken_description_space (2582521050049860859) -->
- <skip />
- <!-- no translation found for spoken_description_mic (615536748882611950) -->
- <skip />
- <!-- no translation found for spoken_description_smiley (2256309826200113918) -->
- <skip />
- <!-- no translation found for spoken_description_return (8178083177238315647) -->
- <skip />
- <!-- no translation found for spoken_description_search (1247236163755920808) -->
- <skip />
- <!-- no translation found for spoken_description_dot (40711082435231673) -->
- <skip />
- <!-- no translation found for spoken_description_language_switch (5507091328222331316) -->
- <skip />
- <!-- no translation found for spoken_description_action_next (8636078276664150324) -->
- <skip />
- <!-- no translation found for spoken_description_action_previous (800872415009336208) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) -->
- <skip />
- <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) -->
- <skip />
- <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) -->
- <skip />
- <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone (6520207943132026264) -->
- <skip />
- <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) -->
- <skip />
- <!-- no translation found for voice_input (3583258583521397548) -->
- <skip />
- <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) -->
- <skip />
- <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) -->
- <skip />
- <!-- no translation found for voice_input_modes_off (3745699748218082014) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) -->
- <skip />
- <!-- no translation found for voice_input_modes_summary_off (63875609591897607) -->
- <skip />
- <!-- no translation found for configure_input_method (373356270290742459) -->
- <skip />
- <!-- no translation found for language_selection_title (1651299598555326750) -->
- <skip />
- <!-- no translation found for select_language (3693815588777926848) -->
- <skip />
- <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
- <skip />
- <!-- no translation found for has_dictionary (6071847973466625007) -->
- <skip />
- <!-- no translation found for prefs_enable_log (6620424505072963557) -->
- <skip />
- <!-- no translation found for prefs_description_log (5827825607258246003) -->
- <skip />
- <!-- no translation found for keyboard_layout (8451164783510487501) -->
- <skip />
- <!-- no translation found for subtype_en_GB (88170601942311355) -->
- <skip />
- <!-- no translation found for subtype_en_US (6160452336634534239) -->
- <skip />
- <!-- no translation found for subtype_es_US (5583145191430180200) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_GB (2179097748724725906) -->
- <skip />
- <!-- no translation found for subtype_with_layout_en_US (1362581347576714579) -->
- <skip />
- <!-- no translation found for subtype_with_layout_es_US (6261791057007890189) -->
- <skip />
- <!-- no translation found for subtype_no_language (141420857808801746) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwerty (2956121451616633133) -->
- <skip />
- <!-- no translation found for subtype_no_language_qwertz (1177848172397202890) -->
- <skip />
- <!-- no translation found for subtype_no_language_azerty (8721460968141187394) -->
- <skip />
- <!-- no translation found for subtype_no_language_dvorak (3122976737669823935) -->
- <skip />
- <!-- no translation found for subtype_no_language_colemak (4205992994906097244) -->
- <skip />
- <!-- no translation found for subtype_no_language_pcqwerty (8840928374394180189) -->
- <skip />
- <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
- <skip />
- <!-- no translation found for add_style (6163126614514489951) -->
- <skip />
- <!-- no translation found for add (8299699805688017798) -->
- <skip />
- <!-- no translation found for remove (4486081658752944606) -->
- <skip />
- <!-- no translation found for save (7646738597196767214) -->
- <skip />
- <!-- no translation found for subtype_locale (8576443440738143764) -->
- <skip />
- <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
- <skip />
- <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
- <skip />
- <!-- no translation found for enable (5031294444630523247) -->
- <skip />
- <!-- no translation found for not_now (6172462888202790482) -->
- <skip />
- <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
- <skip />
- <!-- no translation found for prefs_usability_study_mode (1261130555134595254) -->
- <skip />
- <!-- no translation found for prefs_key_longpress_timeout_settings (1881822418815012326) -->
- <skip />
- <!-- no translation found for prefs_keypress_vibration_duration_settings (1829950405285211668) -->
- <skip />
- <!-- no translation found for prefs_keypress_sound_volume_settings (5875933757082305040) -->
- <skip />
- <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
- <skip />
- <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
- <skip />
- <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
- <skip />
- <!-- no translation found for read_external_dictionary_confirm_install_message (6898610163768980870) -->
- <skip />
- <!-- no translation found for error (8940763624668513648) -->
- <skip />
- <!-- no translation found for button_default (3988017840431881491) -->
- <skip />
-</resources>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index 37f923c26..0d4ccf42d 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Betul-betul pasang fail ini untuk <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Berlaku ralat"</string>
<string name="button_default" msgid="3988017840431881491">"Lalai"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Bahasa &amp; input"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Pilih kaedah input"</string>
</resources>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index b79933f46..f0b3a4623 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Vil du virkelig installere denne filen for <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Det oppsto en feil"</string>
<string name="button_default" msgid="3988017840431881491">"Standard"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Språk og inndata"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Velg inndatametode"</string>
</resources>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 3dba9833b..dc3a9c3f4 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Wilt u dit bestand voor <xliff:g id="LOCALE_NAME">%s</xliff:g> echt installeren?"</string>
<string name="error" msgid="8940763624668513648">"Er is een fout opgetreden"</string>
<string name="button_default" msgid="3988017840431881491">"Standaard"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Taal en invoer"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Invoermethode selecteren"</string>
</resources>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 11602b8fa..de100bc86 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Czy na pewno zainstalować ten plik dla języka: <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Wystąpił błąd"</string>
<string name="button_default" msgid="3988017840431881491">"Domyślne"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Język, klawiatura, głos"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Wybierz metodę wprowadzania"</string>
</resources>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 6e650154f..68a34574f 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Instalar mesmo este ficheiro para <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Ocorreu um erro"</string>
<string name="button_default" msgid="3988017840431881491">"Predefinido"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Idioma e entrada de som"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Escolher o método de entrada"</string>
</resources>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 33f5ecaa5..00ab88ced 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Deseja instalar este arquivo para <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Ocorreu um erro"</string>
<string name="button_default" msgid="3988017840431881491">"Padrão"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Idioma e entrada"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Selecione o método de entrada"</string>
</resources>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index bbef69da4..9eec7f883 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -281,4 +281,8 @@
<skip />
<!-- no translation found for button_default (3988017840431881491) -->
<skip />
+ <!-- no translation found for language_settings (1671153053201809031) -->
+ <skip />
+ <!-- no translation found for select_input_method (4301602374609275003) -->
+ <skip />
</resources>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 5c6ff3fcc..c5a80e397 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Doriți să instalați acest fișier pentru <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"A apărut o eroare"</string>
<string name="button_default" msgid="3988017840431881491">"Prestabilit"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Limbă și introducere de text"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Alegeți metoda de introducere de text"</string>
</resources>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 5e746bb06..13a567808 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Установить этот файл для следующего языка: <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Ошибка"</string>
<string name="button_default" msgid="3988017840431881491">"По умолчанию"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Язык и ввод"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Выберите способ ввода"</string>
</resources>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 9fd979865..0b28bf193 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Chcete nainštalovať tento súbor pre jazyk <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Vyskytla sa chyba"</string>
<string name="button_default" msgid="3988017840431881491">"Predvolené"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Jazyk &amp; vstup"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Zvoliť metódu vstupu"</string>
</resources>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index fa441d712..50f3869d4 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Zares želite namestiti to datoteko za jezik <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Prišlo je do napake"</string>
<string name="button_default" msgid="3988017840431881491">"Privzeto"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Jezik in vnos"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Izbira načina vnosa"</string>
</resources>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 0a9743747..2d13db099 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Желите ли стварно да инсталирате ову датотеку за <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Дошло је до грешке"</string>
<string name="button_default" msgid="3988017840431881491">"Подразумевано"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Језик и унос"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Избор метода уноса"</string>
</resources>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index dd8af36fb..608caad17 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Vill du verkligen installera filen för <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Ett fel uppstod"</string>
<string name="button_default" msgid="3988017840431881491">"Standard"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Språk &amp; inmatning"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Välj inmatningsmetod"</string>
</resources>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index e8a32bfc0..104a5d42e 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Isakinishe faili hii kwa <xliff:g id="LOCALE_NAME">%s</xliff:g> kweli?"</string>
<string name="error" msgid="8940763624668513648">"Kulikuwa na hitilafu"</string>
<string name="button_default" msgid="3988017840431881491">"Chaguo-msingi"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Lugha na uingizaji"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Chagua mbinu ya kuingiza data"</string>
</resources>
diff --git a/java/res/values-sw600dp-land/setup-dimens.xml b/java/res/values-sw600dp-land/setup-dimens.xml
new file mode 100644
index 000000000..9aea21423
--- /dev/null
+++ b/java/res/values-sw600dp-land/setup-dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <dimen name="setup_title_text_size">64sp</dimen>
+ <dimen name="setup_horizontal_padding">96dp</dimen>
+</resources>
diff --git a/java/res/values-sw768dp-land/setup-dimens.xml b/java/res/values-sw768dp-land/setup-dimens.xml
new file mode 100644
index 000000000..0d2af17e3
--- /dev/null
+++ b/java/res/values-sw768dp-land/setup-dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <dimen name="setup_title_text_size">64sp</dimen>
+ <dimen name="setup_horizontal_padding">192dp</dimen>
+</resources>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 008e3e2ea..1db5e91cd 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"ติดตั้งไฟล์นี้สำหรับ <xliff:g id="LOCALE_NAME">%s</xliff:g> จริงๆ หรือ"</string>
<string name="error" msgid="8940763624668513648">"เกิดข้อผิดพลาด"</string>
<string name="button_default" msgid="3988017840431881491">"ค่าเริ่มต้น"</string>
+ <string name="language_settings" msgid="1671153053201809031">"ภาษาและการป้อนข้อมูล"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"เลือกวิธีการป้อนข้อมูล"</string>
</resources>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index ae29e6af3..adf0a1982 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"I-install talaga ang file na ito para sa <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Nagkaroon ng error"</string>
<string name="button_default" msgid="3988017840431881491">"Default"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Wika at input"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Pumili ng pamamaraan ng pag-input"</string>
</resources>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index eb8f2dc1f..fd80fea5b 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"<xliff:g id="LOCALE_NAME">%s</xliff:g> için bu dosya gerçekten yüklensin mi?"</string>
<string name="error" msgid="8940763624668513648">"Bir hata oluştu"</string>
<string name="button_default" msgid="3988017840431881491">"Varsayılan"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Dil ve giriş"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Giriş yöntemini seçin"</string>
</resources>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 5eaad63d2..2e2fdfcff 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Справді встановити цей файл для такої мови: <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Сталася помилка"</string>
<string name="button_default" msgid="3988017840431881491">"За умовчанням"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Мова та введення"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Вибрати метод введення"</string>
</resources>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index fd778d5ee..6721980cf 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Thực sự cài đặt tệp này cho <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
<string name="error" msgid="8940763624668513648">"Đã xảy ra lỗi"</string>
<string name="button_default" msgid="3988017840431881491">"Mặc định"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Ngôn ngữ và phương thức nhập"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Chọn phương thức nhập"</string>
</resources>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index bc94938aa..ebb6b9161 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"确定要为<xliff:g id="LOCALE_NAME">%s</xliff:g>安装此文件吗?"</string>
<string name="error" msgid="8940763624668513648">"出现错误"</string>
<string name="button_default" msgid="3988017840431881491">"默认"</string>
+ <string name="language_settings" msgid="1671153053201809031">"语言和输入法"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"选择输入法"</string>
</resources>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 0bbd30b8f..7d4ea72eb 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"準備為<xliff:g id="LOCALE_NAME">%s</xliff:g>版本安裝這個檔案嗎?"</string>
<string name="error" msgid="8940763624668513648">"發生錯誤"</string>
<string name="button_default" msgid="3988017840431881491">"預設"</string>
+ <string name="language_settings" msgid="1671153053201809031">"語言與輸入設定"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"選擇輸入法"</string>
</resources>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 5848b955d..29ed595b7 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -157,4 +157,6 @@
<string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Ufuna ukufakela i-<xliff:g id="LOCALE_NAME">%s</xliff:g> leli fayela ngokweqiniso?"</string>
<string name="error" msgid="8940763624668513648">"Kube nephutha"</string>
<string name="button_default" msgid="3988017840431881491">"Okuzenzakalelayo"</string>
+ <string name="language_settings" msgid="1671153053201809031">"Ulimi nokokufakwayo"</string>
+ <string name="select_input_method" msgid="4301602374609275003">"Khetha indlela yokufaka"</string>
</resources>
diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml
index c0ea321ce..8a8049f1f 100644
--- a/java/res/values/colors.xml
+++ b/java/res/values/colors.xml
@@ -53,4 +53,9 @@
<color name="spacebar_text_color_ics">#FFC0C0C0</color>
<color name="spacebar_text_shadow_color_ics">#80000000</color>
<color name="typed_word_color_ics">@color/highlight_color_ics</color>
+ <!-- Color resources for setup wizard and tutorial -->
+ <color name="setup_background">#FFEBEBEB</color>
+ <color name="setup_text_dark">#FF707070</color>
+ <color name="setup_text_action">@android:color/holo_blue_light</color>
+ <color name="setup_step_background">@android:color/background_light</color>
</resources>
diff --git a/java/res/values/setup-dimens.xml b/java/res/values/setup-dimens.xml
new file mode 100644
index 000000000..007906dc0
--- /dev/null
+++ b/java/res/values/setup-dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <dimen name="setup_title_text_size">46sp</dimen>
+ <dimen name="setup_horizontal_padding">16dp</dimen>
+</resources>
diff --git a/java/res/values/setup-styles.xml b/java/res/values/setup-styles.xml
new file mode 100644
index 000000000..cfc689a78
--- /dev/null
+++ b/java/res/values/setup-styles.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="setupTitleStyle">
+ <item name="android:textColor">@color/setup_text_dark</item>
+ <item name="android:textSize">@dimen/setup_title_text_size</item>
+ </style>
+ <style name="setupStepBulletStyle">
+ <item name="android:textColor">@color/setup_text_dark</item>
+ <item name="android:textSize">22sp</item>
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_weight">1.0</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">center_horizontal</item>
+ </style>
+ <style name="setupStepTitleStyle">
+ <item name="android:background">@color/setup_step_background</item>
+ <item name="android:textColor">@color/setup_text_dark</item>
+ <item name="android:textSize">22sp</item>
+ </style>
+ <style name="setupStepInstructionStyle">
+ <item name="android:background">@color/setup_step_background</item>
+ <item name="android:textColor">@color/setup_text_dark</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+ <style name="setupStepActionLabelStyle">
+ <item name="android:background">@color/setup_step_background</item>
+ <item name="android:textColor">@color/setup_text_action</item>
+ <item name="android:textSize">18sp</item>
+ </style>
+</resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index ee79b450e..e89174b02 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -223,6 +223,29 @@
<!-- Spoken feedback after changing to the shifted phone dialer (symbols) keyboard. -->
<string name="spoken_description_mode_phone_shift">Phone symbols mode</string>
+ <!-- Spoken feedback when the keyboard is hidden. -->
+ <string name="announce_keyboard_hidden">Keyboard hidden</string>
+ <!-- Spoken feedback when the keyboard mode changes. -->
+ <string name="announce_keyboard_mode">Showing <xliff:g id="mode" example="email">%s</xliff:g> keyboard</string>
+ <!-- Description of the keyboard mode for entering dates. -->
+ <string name="keyboard_mode_date">date</string>
+ <!-- Description of the keyboard mode for entering dates and times. -->
+ <string name="keyboard_mode_date_time">date and time</string>
+ <!-- Description of the keyboard mode for entering email addresses. -->
+ <string name="keyboard_mode_email">email</string>
+ <!-- Description of the keyboard mode for entering text messages. -->
+ <string name="keyboard_mode_im">messaging</string>
+ <!-- Description of the keyboard mode for entering numbers. -->
+ <string name="keyboard_mode_number">number</string>
+ <!-- Description of the keyboard mode for entering phone numbers. -->
+ <string name="keyboard_mode_phone">phone</string>
+ <!-- Description of the keyboard mode for entering generic text. -->
+ <string name="keyboard_mode_text">text</string>
+ <!-- Description of the keyboard mode for entering times. -->
+ <string name="keyboard_mode_time">time</string>
+ <!-- Description of the keyboard mode for entering URLs. -->
+ <string name="keyboard_mode_url">URL</string>
+
<!-- Preferences item for enabling speech input -->
<string name="voice_input">Voice input key</string>
@@ -408,4 +431,32 @@
<!-- Title of the button to revert to the default value of the device in the settings dialog [CHAR LIMIT=15] -->
<string name="button_default">Default</string>
+
+ <!-- TODO: Remove translatable="false" once wordings are finalized. -->
+ <!-- Title of the setup wizard. [CHAR LIMT=40] -->
+ <string name="setup_title" translatable="false">"Installing <xliff:g id="application_name">%s</xliff:g>"</string>
+ <!-- Ordinal number of the 1st step in the setup wizard. [CHAR LIMIT=5] -->
+ <string name="setup_step1_bullet" translatable="false">1</string>
+ <!-- Title of the 1st step in the setup wizard. [CHAR LIMIT=64] -->
+ <string name="setup_step1_title" translatable="false">"Enable <xliff:g id="application_name">%s</xliff:g> in settings."</string>
+ <!-- Detailed instruction of the 1st step in the setup wizard. [CHAR LIMIT=80] -->
+ <string name="setup_step1_instruction" translatable="false">"For security, please check \"<xliff:g id="application_name">%s</xliff:g>\""</string>
+ <!-- Ordinal number of the 2nd step in the setup wizard. [CHAR LIMIT=5] -->
+ <string name="setup_step2_bullet" translatable="false">2</string>
+ <!-- Title of the 2nd step in the setup wizard. [CHAR LIMIT=64] -->
+ <string name="setup_step2_title" translatable="false">"Switch to <xliff:g id="application_name">%s</xliff:g>."</string>
+ <!-- Detailed instruction of the 2nd step in the setup wizard. [CHAR LIMIT=80] -->
+ <string name="setup_step2_instruction" translatable="false">"Now that you've enabled <xliff:g id="application_name">%s</xliff:g>, you can switch to it."</string>
+ <!-- Ordinal number of the 3rd step in the setup wizard. [CHAR LIMIT=5] -->
+ <string name="setup_step3_bullet" translatable="false">3</string>
+ <!-- Title of the 3rd step in the setup wizard. [CHAR LIMIT=64] -->
+ <string name="setup_step3_title" translatable="false">"Congratulations, you're all set!"</string>
+ <!-- Detailed instruction of the 3rd step in the setup wizard. [CHAR LIMIT=80] -->
+ <string name="setup_step3_instruction" translatable="false">Configure additional languages</string>
+ <!-- Title of the Language & input settings. This should be aligned with msgid="5292716747264442359" -->
+ <string name="language_settings">Language &amp; input</string>
+ <!-- Title of the Input method picker. This should be aligned with msgid="4653387336791222978" -->
+ <string name="select_input_method">Choose input method</string>
+ <!-- Option to show setup wizard icon. [CHAR LIMIT=30]-->
+ <string name="show_setup_wizard_icon" translatable="false">Show setup wizard icon</string>
</resources>
diff --git a/java/res/xml-sw600dp/keys_pcqwerty3_right2.xml b/java/res/xml-sw600dp/keys_pcqwerty3_right2.xml
index a0e5cbb92..0e3013afe 100644
--- a/java/res/xml-sw600dp/keys_pcqwerty3_right2.xml
+++ b/java/res/xml-sw600dp/keys_pcqwerty3_right2.xml
@@ -28,19 +28,9 @@
<Key
latin:keyLabel=";"
latin:moreKeys=":" />
- <!-- 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.
- moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" -->
<Key
latin:keyLabel="\'"
- latin:moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x2018;,&#x2019;,&#x201A;,&#x201B;,&quot;" />
+ latin:moreKeys="!fixedColumnOrder!3,!text/double_quotes,!text/single_quotes" />
</case>
<default>
<Key
@@ -48,20 +38,10 @@
latin:keyHintLabel=":"
latin:moreKeys=":"
latin:keyStyle="hasShiftedLetterHintStyle" />
- <!-- 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.
- moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" -->
<Key
latin:keyLabel="\'"
latin:keyHintLabel="&quot;"
- latin:moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x2018;,&#x2019;,&#x201A;,&#x201B;,&quot;"
+ latin:moreKeys="!fixedColumnOrder!4,!text/double_quotes,&quot;,!text/single_quotes"
latin:keyStyle="hasShiftedLetterHintStyle" />
</default>
</switch>
diff --git a/java/res/xml-v16/key_hindi1_shift.xml b/java/res/xml-v16/key_hindi1_shift.xml
new file mode 100644
index 000000000..19b964367
--- /dev/null
+++ b/java/res/xml-v16/key_hindi1_shift.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0903: "ः" DEVANAGARI SIGN VISARGA -->
+ <Key
+ latin:keyLabel="&#x0903;"
+ latin:keyLabelFlags="fontNormal" />
+</merge>
diff --git a/java/res/xml-v16/key_hindi3_right.xml b/java/res/xml-v16/key_hindi3_right.xml
new file mode 100644
index 000000000..232810f98
--- /dev/null
+++ b/java/res/xml-v16/key_hindi3_right.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+093C: "़" DEVANAGARI SIGN NUKTA
+ U+097D: "ॽ" DEVANAGARI LETTER GLOTTAL STOP
+ U+0970: "॰" DEVANAGARI ABBREVIATION SIGN
+ U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA -->
+ <Key
+ latin:keyLabel="&#x093C;"
+ latin:moreKeys="&#x097D;,&#x0970;,&#x093D;"
+ latin:keyLabelFlags="fontNormal" />
+</merge>
diff --git a/java/res/xml-v16/key_hindi3_shift_left.xml b/java/res/xml-v16/key_hindi3_shift_left.xml
new file mode 100644
index 000000000..1eb1768a1
--- /dev/null
+++ b/java/res/xml-v16/key_hindi3_shift_left.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0901: "ँ" DEVANAGARI SIGN CANDRABINDU
+ U+0945: "ॅ" DEVANAGARI VOWEL SIGN CANDRA E -->
+ <Key
+ latin:keyLabel="&#x0901;"
+ latin:moreKeys="&#x0945;"
+ latin:keyLabelFlags="fontNormal" />
+</merge>
diff --git a/java/res/xml-v16/key_hindi3_shift_right.xml b/java/res/xml-v16/key_hindi3_shift_right.xml
new file mode 100644
index 000000000..0f26cb55c
--- /dev/null
+++ b/java/res/xml-v16/key_hindi3_shift_right.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0943: "ृ" DEVANAGARI VOWEL SIGN VOCALIC R
+ U+0944: "ॄ" DEVANAGARI VOWEL SIGN VOCALIC RR -->
+ <Key
+ latin:keyLabel="&#x0943;"
+ latin:moreKeys="&#x0944;"
+ latin:keyLabelFlags="fontNormal" />
+</merge>
diff --git a/java/res/xml-v16/keys_hindi1_left5.xml b/java/res/xml-v16/keys_hindi1_left5.xml
new file mode 100644
index 000000000..e3ad299ff
--- /dev/null
+++ b/java/res/xml-v16/keys_hindi1_left5.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+094C: "ौ" DEVANAGARI VOWEL SIGN AU
+ U+094C/U+0902: "ौं" DEVANAGARI VOWEL SIGN AU/DEVANAGARI SIGN ANUSVARA
+ U+0967: "१" DEVANAGARI DIGIT ONE -->
+ <Key
+ latin:keyLabel="&#x094C;"
+ latin:moreKeys="&#x094C;&#x0902;,%"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="&#x0967;,1"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+0948: "ै" DEVANAGARI VOWEL SIGN AI
+ U+0948/U+0902: "ैं" DEVANAGARI VOWEL SIGN AI/DEVANAGARI SIGN ANUSVARA
+ U+0968: "२" DEVANAGARI DIGIT TWO -->
+ <Key
+ latin:keyLabel="&#x0948;"
+ latin:moreKeys="&#x0948;&#x0902;,%"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="&#x0968;,2"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+093E: "ा" DEVANAGARI VOWEL SIGN AA
+ U+093E/U+0902: "ां" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN ANUSVARA
+ U+093E/U+0901: "ाँ" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN CANDRABINDU
+ U+0969: "३" DEVANAGARI DIGIT THREE -->
+ <Key
+ latin:keyLabel="&#x093E;"
+ latin:moreKeys="&#x093E;&#x0902;,&#x093E;&#x0901;,%"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="&#x0969;,3"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+0940: "ी" DEVANAGARI VOWEL SIGN II
+ U+0940/U+0902: "ीं" DEVANAGARI VOWEL SIGN II/DEVANAGARI SIGN ANUSVARA
+ U+096A: "४" DEVANAGARI DIGIT FOUR -->
+ <Key
+ latin:keyLabel="&#x0940;"
+ latin:moreKeys="&#x0940;&#x0902;,%"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="&#x096A;,4"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+0942: "ू" DEVANAGARI VOWEL SIGN UU
+ U+0942/U+0902: "ूं" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN ANUSVARA
+ U+0942/U+0901: "ूँ" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN CANDRABINDU
+ U+096B: "५" DEVANAGARI DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x0942;"
+ latin:moreKeys="&#x0942;&#x0902;,&#x0942;&#x0901;,%"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="&#x096B;,5"
+ latin:keyLabelFlags="fontNormal" />
+</merge>
diff --git a/java/res/xml-v16/keys_hindi2_left5.xml b/java/res/xml-v16/keys_hindi2_left5.xml
new file mode 100644
index 000000000..05c4f57e9
--- /dev/null
+++ b/java/res/xml-v16/keys_hindi2_left5.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+094B: "ो" DEVANAGARI VOWEL SIGN O
+ U+094B/U+0902: "қं" DEVANAGARI VOWEL SIGN O/DEVANAGARI SIGN ANUSVARA
+ U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O
+ U+094A: "ॊ" DEVANAGARI VOWEL SIGN SHORT O -->
+ <Key
+ latin:keyLabel="&#x094B;"
+ latin:moreKeys="&#x094B;&#x0902;,&#x0949;,&#x094A;"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+0947: "े" DEVANAGARI VOWEL SIGN E
+ U+0947/U+0902: "ें" DEVANAGARI VOWEL SIGN E/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x0947;"
+ latin:moreKeys="&#x0947;&#x0902;"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+094D: "्" DEVANAGARI SIGN VIRAMA -->
+ <Key
+ latin:keyLabel="&#x094D;"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+093F: "ि" DEVANAGARI VOWEL SIGN I
+ U+093F/U+0902: "िं" DEVANAGARI VOWEL SIGN I/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x093F;"
+ latin:moreKeys="&#x093F;&#x0902;"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+0941: "ु" DEVANAGARI VOWEL SIGN U
+ U+0941/U+0902: "ुं" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN ANUSVARA
+ U+0941/U+0901: "ुँ" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x0941;"
+ latin:moreKeys="&#x0941;&#x0902;,&#x0941;&#x0901;"
+ latin:keyLabelFlags="fontNormal" />
+</merge>
diff --git a/java/res/xml-v16/keys_hindi3_left2.xml b/java/res/xml-v16/keys_hindi3_left2.xml
new file mode 100644
index 000000000..9474c1763
--- /dev/null
+++ b/java/res/xml-v16/keys_hindi3_left2.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O -->
+ <Key
+ latin:keyLabel="&#x0949;"
+ latin:keyLabelFlags="fontNormal" />
+ <!-- U+0902: "ं" DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x0902;"
+ latin:keyLabelFlags="fontNormal" />
+</merge>
diff --git a/java/res/xml/key_hindi1_shift.xml b/java/res/xml/key_hindi1_shift.xml
new file mode 100644
index 000000000..0db5ae9af
--- /dev/null
+++ b/java/res/xml/key_hindi1_shift.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0903: "ः" DEVANAGARI SIGN VISARGA -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0903;"
+ latin:code="0x0903"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+</merge>
diff --git a/java/res/xml/key_hindi3_right.xml b/java/res/xml/key_hindi3_right.xml
new file mode 100644
index 000000000..5a97355f6
--- /dev/null
+++ b/java/res/xml/key_hindi3_right.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+093C: "़" DEVANAGARI SIGN NUKTA
+ U+097D: "ॽ" DEVANAGARI LETTER GLOTTAL STOP
+ U+0970: "॰" DEVANAGARI ABBREVIATION SIGN
+ U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x093C;"
+ latin:code="0x093C"
+ latin:moreKeys="&#x25CC;&#x097D;|&#x097D;,&#x25CC;&#x0970;|&#x0970;,&#x25CC;&#x093D;|&#x093D;"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+</merge>
diff --git a/java/res/xml/key_hindi3_shift_left.xml b/java/res/xml/key_hindi3_shift_left.xml
new file mode 100644
index 000000000..c5e2f1386
--- /dev/null
+++ b/java/res/xml/key_hindi3_shift_left.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0901: "ँ" DEVANAGARI SIGN CANDRABINDU
+ U+0945: "ॅ" DEVANAGARI VOWEL SIGN CANDRA E -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0901;"
+ latin:code="0x0901"
+ latin:moreKeys="&#x25CC;&#x0945;|&#x0945;"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+</merge>
diff --git a/java/res/xml/key_hindi3_shift_right.xml b/java/res/xml/key_hindi3_shift_right.xml
new file mode 100644
index 000000000..0da116ab8
--- /dev/null
+++ b/java/res/xml/key_hindi3_shift_right.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0943: "ृ" DEVANAGARI VOWEL SIGN VOCALIC R
+ U+0944: "ॄ" DEVANAGARI VOWEL SIGN VOCALIC RR -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0943;"
+ latin:code="0x0943"
+ latin:moreKeys="&#x25CC;&#x0944;|&#x0944;"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+</merge>
diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml
index 61a515bad..5976e95db 100644
--- a/java/res/xml/key_styles_enter.xml
+++ b/java/res/xml/key_styles_enter.xml
@@ -104,7 +104,7 @@
latin:parentStyle="defaultEnterKeyStyle" />
<key-style
latin:styleName="defaultActionEnterKeyStyle"
- latin:code="!code/key_action_enter"
+ latin:code="!code/key_enter"
latin:keyIcon="!icon/undefined"
latin:backgroundType="action"
latin:parentStyle="defaultEnterKeyStyle" />
diff --git a/java/res/xml/keys_hindi1_left5.xml b/java/res/xml/keys_hindi1_left5.xml
new file mode 100644
index 000000000..8757afeaf
--- /dev/null
+++ b/java/res/xml/keys_hindi1_left5.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+094C: "ौ" DEVANAGARI VOWEL SIGN AU
+ U+094C/U+0902: "ौं" DEVANAGARI VOWEL SIGN AU/DEVANAGARI SIGN ANUSVARA
+ U+0967: "१" DEVANAGARI DIGIT ONE -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x094C;"
+ latin:code="0x094C"
+ latin:moreKeys="&#x25CC;&#x094C;&#x0902;|&#x094C;&#x0902;,%"
+ latin:keyHintLabel="1"
+ latin:additionalMoreKeys="&#x0967;,1"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0948: "ै" DEVANAGARI VOWEL SIGN AI
+ U+0948/U+0902: "ैं" DEVANAGARI VOWEL SIGN AI/DEVANAGARI SIGN ANUSVARA
+ U+0968: "२" DEVANAGARI DIGIT TWO -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0948;"
+ latin:code="0x0948"
+ latin:moreKeys="&#x25CC;&#x0948;&#x0902;|&#x0948;&#x0902;,%"
+ latin:keyHintLabel="2"
+ latin:additionalMoreKeys="&#x0968;,2"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+093E: "ा" DEVANAGARI VOWEL SIGN AA
+ U+093E/U+0902: "ां" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN ANUSVARA
+ U+093E/U+0901: "ाँ" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN CANDRABINDU
+ U+0969: "३" DEVANAGARI DIGIT THREE -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x093E;"
+ latin:code="0x093E"
+ latin:moreKeys="&#x25CC;&#x093E;&#x0902;|&#x093E;&#x0902;,&#x25CC;&#x093E;&#x0901;|&#x093E;&#x0901;,%"
+ latin:keyHintLabel="3"
+ latin:additionalMoreKeys="&#x0969;,3"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0940: "ी" DEVANAGARI VOWEL SIGN II
+ U+0940/U+0902: "ीं" DEVANAGARI VOWEL SIGN II/DEVANAGARI SIGN ANUSVARA
+ U+096A: "४" DEVANAGARI DIGIT FOUR -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0940;"
+ latin:code="0x0940"
+ latin:moreKeys="&#x25CC;&#x0940;&#x0902;|&#x0940;&#x0902;,%"
+ latin:keyHintLabel="4"
+ latin:additionalMoreKeys="&#x096A;,4"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0942: "ू" DEVANAGARI VOWEL SIGN UU
+ U+0942/U+0902: "ूं" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN ANUSVARA
+ U+0942/U+0901: "ूँ" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN CANDRABINDU
+ U+096B: "५" DEVANAGARI DIGIT FIVE -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0942;"
+ latin:code="0x0942"
+ latin:moreKeys="&#x25CC;&#x0942;&#x0902;|&#x0942;&#x0902;,&#x25CC;&#x0942;&#x0901;|&#x0942;&#x0901;,%"
+ latin:keyHintLabel="5"
+ latin:additionalMoreKeys="&#x096B;,5"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+</merge>
diff --git a/java/res/xml/keys_hindi2_left5.xml b/java/res/xml/keys_hindi2_left5.xml
new file mode 100644
index 000000000..4c3a5e051
--- /dev/null
+++ b/java/res/xml/keys_hindi2_left5.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+094B: "ो" DEVANAGARI VOWEL SIGN O
+ U+094B/U+0902: "қं" DEVANAGARI VOWEL SIGN O/DEVANAGARI SIGN ANUSVARA
+ U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O
+ U+094A: "ॊ" DEVANAGARI VOWEL SIGN SHORT O -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x094B;"
+ latin:code="0x094B"
+ latin:moreKeys="&#x25CC;&#x094B;&#x0902;|&#x094B;&#x0902;,&#x25CC;&#x0949;,&#x094A;|&#x0949;,&#x094A;"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0947: "े" DEVANAGARI VOWEL SIGN E
+ U+0947/U+0902: "ें" DEVANAGARI VOWEL SIGN E/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0947;"
+ latin:code="0x0947"
+ latin:moreKeys="&#x25CC;&#x0947;&#x0902;|&#x0947;&#x0902;"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+094D: "्" DEVANAGARI SIGN VIRAMA -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x094D;"
+ latin:code="0x094D"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+093F: "ि" DEVANAGARI VOWEL SIGN I
+ U+093F/U+0902: "िं" DEVANAGARI VOWEL SIGN I/DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x093F;&#x25CC;"
+ latin:code="0x093F"
+ latin:moreKeys="&#x093F;&#x25CC;&#x0902;|&#x093F;&#x0902;"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0941: "ु" DEVANAGARI VOWEL SIGN U
+ U+0941/U+0902: "ुं" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN ANUSVARA
+ U+0941/U+0901: "ुँ" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN CANDRABINDU -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0941;"
+ latin:code="0x0941"
+ latin:moreKeys="&#x25CC;&#x0941;&#x0902;|&#x0941;&#x0902;,&#x25CC;&#x0941;&#x0901;|&#x0941;&#x0901;"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+</merge>
diff --git a/java/res/xml/keys_hindi3_left2.xml b/java/res/xml/keys_hindi3_left2.xml
new file mode 100644
index 000000000..4f1ad16ef
--- /dev/null
+++ b/java/res/xml/keys_hindi3_left2.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- The code point U+25CC for key label is needed because the font rendering system prior to
+ API version 16 can't automatically render dotted circle for incomplete combining letter
+ of Hindi. The files named res/xml/{key,keys}_hindi*.xml have this U+25CC hack, although the
+ counterpart files named res/xml-v16/{key,keys}_hindi*.xml don't have this hack. -->
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0949;"
+ latin:code="0x0949"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+ <!-- U+25CC: "◌" DOTTED CIRCLE
+ U+0902: "ं" DEVANAGARI SIGN ANUSVARA -->
+ <Key
+ latin:keyLabel="&#x25CC;&#x0902;"
+ latin:code="0x0902"
+ latin:keyLabelFlags="fontNormal|followKeyLetterRatio" />
+</merge>
diff --git a/java/res/xml/keys_pcqwerty3_right2.xml b/java/res/xml/keys_pcqwerty3_right2.xml
index fd9d3b8b0..aa150afb3 100644
--- a/java/res/xml/keys_pcqwerty3_right2.xml
+++ b/java/res/xml/keys_pcqwerty3_right2.xml
@@ -30,25 +30,15 @@
latin:moreKeys=":" />
<Key
latin:keyLabel="\'"
- latin:moreKeys="&quot;" />
+ latin:moreKeys="!fixedColumnOrder!4,!text/double_quotes,&quot;,!text/single_quotes" />
</case>
<!-- keyboardLayoutSetElement="alphabet*Shifted|symbols*" -->
<default>
<Key
latin:keyLabel=":" />
- <!-- 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.
- moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" -->
<Key
latin:keyLabel="&quot;"
- latin:moreKeys="!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x2018;,&#x2019;,&#x201A;,&#x201B;" />
+ latin:moreKeys="!fixedColumnOrder!3,!text/double_quotes,!text/single_quotes" />
</default>
</switch>
</merge>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 5ed0bb029..e5fef8834 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -60,7 +60,11 @@
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="@string/dictionary_pack_package_name"
- android:targetClass="@string/dictionary_pack_settings_activity" />
+ android:targetClass="@string/dictionary_pack_settings_activity">
+ <extra
+ android:name="clientId"
+ android:value="@string/dictionary_pack_client_id" />
+ </intent>
</PreferenceScreen>
<ListPreference
android:key="auto_correction_threshold"
@@ -141,7 +145,7 @@
android:fragment="com.android.inputmethod.latin.AdditionalSubtypeSettings"
android:key="custom_input_styles"
android:title="@string/custom_input_styles_title" />
- <!-- Values for popup dismiss delay are added programatically -->
+ <!-- Values for popup dismiss delay are added programmatically -->
<CheckBoxPreference
android:key="pref_sliding_key_input_preview"
android:title="@string/sliding_key_input_preview"
@@ -167,6 +171,11 @@
android:key="pref_keypress_sound_volume"
android:title="@string/prefs_keypress_sound_volume_settings"
latin:maxValue="100" /> <!-- percent -->
+ <!-- The show setup wizard icon settings shouldn't be persistent and the default value
+ is added programmatically. -->
+ <CheckBoxPreference
+ android:key="pref_show_setup_wizard_icon"
+ android:title="@string/show_setup_wizard_icon" />
</PreferenceScreen>
<PreferenceScreen
android:key="debug_settings"
diff --git a/java/res/xml/row_symbols_shift4.xml b/java/res/xml/row_symbols_shift4.xml
index 1bfb5ecd1..99a685c45 100644
--- a/java/res/xml/row_symbols_shift4.xml
+++ b/java/res/xml/row_symbols_shift4.xml
@@ -27,13 +27,11 @@
<Key
latin:keyStyle="toAlphaKeyStyle"
latin:keyWidth="15%p" />
- <!-- 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. -->
- <!-- latin:keyLabelFlags="hasPopupHint" -->
- <!-- latin:moreKeys="&#x201F;" -->
- <!-- U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
+ <!-- U+201A: "‚" SINGLE LOW-9 QUOTATION MARK
+ U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
<Key
latin:keyLabel="&#x201E;"
+ latin:moreKeys="&#x201A;"
latin:backgroundType="functional" />
<include
latin:keyXPos="25%p"
diff --git a/java/res/xml/rowkeys_hindi1.xml b/java/res/xml/rowkeys_hindi1.xml
index 11208045c..a761a6c69 100644
--- a/java/res/xml/rowkeys_hindi1.xml
+++ b/java/res/xml/rowkeys_hindi1.xml
@@ -61,10 +61,11 @@
<Key
latin:keyLabel="&#x092D;"
latin:keyLabelFlags="fontNormal" />
- <!-- U+0903: "ः" DEVANAGARI SIGN VISARGA -->
- <Key
- latin:keyLabel="&#x0903;"
- latin:keyLabelFlags="fontNormal" />
+ <!-- Because the font rendering system prior to API version 16 can't automatically
+ render dotted circle for incomplete combining letter of Hindi, different set of
+ Key definitions are needed based on the API version. -->
+ <include
+ latin:keyboardLayout="@xml/key_hindi1_shift" />
<!-- U+0918: "घ" DEVANAGARI LETTER GHA -->
<Key
latin:keyLabel="&#x0918;"
@@ -86,53 +87,11 @@
latin:keyLabelFlags="fontNormal" />
</case>
<default>
- <!-- U+094C: "ौ" DEVANAGARI VOWEL SIGN AU
- U+094C/U+0902: "ौं" DEVANAGARI VOWEL SIGN AU/DEVANAGARI SIGN ANUSVARA
- U+0967: "१" DEVANAGARI DIGIT ONE -->
- <Key
- latin:keyLabel="&#x094C;"
- latin:moreKeys="&#x094C;&#x0902;,%"
- latin:keyHintLabel="1"
- latin:additionalMoreKeys="&#x0967;,1"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+0948: "ै" DEVANAGARI VOWEL SIGN AI
- U+0948/U+0902: "ैं" DEVANAGARI VOWEL SIGN AI/DEVANAGARI SIGN ANUSVARA
- U+0968: "२" DEVANAGARI DIGIT TWO -->
- <Key
- latin:keyLabel="&#x0948;"
- latin:moreKeys="&#x0948;&#x0902;,%"
- latin:keyHintLabel="2"
- latin:additionalMoreKeys="&#x0968;,2"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+093E: "ा" DEVANAGARI VOWEL SIGN AA
- U+093E/U+0902: "ां" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN ANUSVARA
- U+093E/U+0901: "ाँ" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN CANDRABINDU
- U+0969: "३" DEVANAGARI DIGIT THREE -->
- <Key
- latin:keyLabel="&#x093E;"
- latin:moreKeys="&#x093E;&#x0902;,&#x093E;&#x0901;,%"
- latin:keyHintLabel="3"
- latin:additionalMoreKeys="&#x0969;,3"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+0940: "ी" DEVANAGARI VOWEL SIGN II
- U+0940/U+0902: "ीं" DEVANAGARI VOWEL SIGN II/DEVANAGARI SIGN ANUSVARA
- U+096A: "४" DEVANAGARI DIGIT FOUR -->
- <Key
- latin:keyLabel="&#x0940;"
- latin:moreKeys="&#x0940;&#x0902;,%"
- latin:keyHintLabel="4"
- latin:additionalMoreKeys="&#x096A;,4"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+0942: "ू" DEVANAGARI VOWEL SIGN UU
- U+0942/U+0902: "ूं" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN ANUSVARA
- U+0942/U+0901: "ूँ" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN CANDRABINDU
- U+096B: "५" DEVANAGARI DIGIT FIVE -->
- <Key
- latin:keyLabel="&#x0942;"
- latin:moreKeys="&#x0942;&#x0902;,&#x0942;&#x0901;,%"
- latin:keyHintLabel="5"
- latin:additionalMoreKeys="&#x096B;,5"
- latin:keyLabelFlags="fontNormal" />
+ <!-- Because the font rendering system prior to API version 16 can't automatically
+ render dotted circle for incomplete combining letter of Hindi, different set of
+ Key definitions are needed based on the API version. -->
+ <include
+ latin:keyboardLayout="@xml/keys_hindi1_left5" />
<!-- U+092C: "ब" DEVANAGARI LETTER BA
U+092C/U+0952: "ब॒" DEVANAGARI LETTER BA/DEVANAGARI STRESS SIGN ANUDATTA -->
<Key
diff --git a/java/res/xml/rowkeys_hindi2.xml b/java/res/xml/rowkeys_hindi2.xml
index e7c67dbe7..9545b840f 100644
--- a/java/res/xml/rowkeys_hindi2.xml
+++ b/java/res/xml/rowkeys_hindi2.xml
@@ -96,37 +96,11 @@
latin:keyLabelFlags="fontNormal" />
</case>
<default>
- <!-- U+094B: "ो" DEVANAGARI VOWEL SIGN O
- U+094B/U+0902: "қं" DEVANAGARI VOWEL SIGN O/DEVANAGARI SIGN ANUSVARA
- U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O
- U+094A: "ॊ" DEVANAGARI VOWEL SIGN SHORT O -->
- <Key
- latin:keyLabel="&#x094B;"
- latin:moreKeys="&#x094B;&#x0902;,&#x0949;,&#x094A;"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+0947: "े" DEVANAGARI VOWEL SIGN E
- U+0947/U+0902: "ें" DEVANAGARI VOWEL SIGN E/DEVANAGARI SIGN ANUSVARA -->
- <Key
- latin:keyLabel="&#x0947;"
- latin:moreKeys="&#x0947;&#x0902;"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+094D: "्" DEVANAGARI SIGN VIRAMA -->
- <Key
- latin:keyLabel="&#x094D;"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+093F: "ि" DEVANAGARI VOWEL SIGN I
- U+093F/U+0902: "िं" DEVANAGARI VOWEL SIGN I/DEVANAGARI SIGN ANUSVARA -->
- <Key
- latin:keyLabel="&#x093F;"
- latin:moreKeys="&#x093F;&#x0902;"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+0941: "ु" DEVANAGARI VOWEL SIGN U
- U+0941/U+0902: "ुं" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN ANUSVARA
- U+0941/U+0901: "ुँ" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN CANDRABINDU -->
- <Key
- latin:keyLabel="&#x0941;"
- latin:moreKeys="&#x0941;&#x0902;,&#x0941;&#x0901;"
- latin:keyLabelFlags="fontNormal" />
+ <!-- Because the font rendering system prior to API version 16 can't automatically
+ render dotted circle for incomplete combining letter of Hindi, different set of
+ Key definitions are needed based on the API version. -->
+ <include
+ latin:keyboardLayout="@xml/keys_hindi2_left5" />
<!-- U+092A: "प" DEVANAGARI LETTER PA -->
<Key
latin:keyLabel="&#x092A;"
diff --git a/java/res/xml/rowkeys_hindi3.xml b/java/res/xml/rowkeys_hindi3.xml
index ebbff3e33..3014907ed 100644
--- a/java/res/xml/rowkeys_hindi3.xml
+++ b/java/res/xml/rowkeys_hindi3.xml
@@ -29,12 +29,11 @@
<Key
latin:keyLabel="&#x0911;"
latin:keyLabelFlags="fontNormal" />
- <!-- U+0901: "ँ" DEVANAGARI SIGN CANDRABINDU
- U+0945: "ॅ" DEVANAGARI VOWEL SIGN CANDRA E-->
- <Key
- latin:keyLabel="&#x0901;"
- latin:moreKeys="&#x0945;"
- latin:keyLabelFlags="fontNormal" />
+ <!-- Because the font rendering system prior to API version 16 can't automatically
+ render dotted circle for incomplete combining letter of Hindi, different set of
+ Key definitions are needed based on the API version. -->
+ <include
+ latin:keyboardLayout="@xml/key_hindi3_shift_left" />
<!-- U+0923: "ण" DEVANAGARI LETTER NNA -->
<Key
latin:keyLabel="&#x0923;"
@@ -56,26 +55,22 @@
<Key
latin:keyLabel="&#x0937;"
latin:keyLabelFlags="fontNormal" />
- <!-- U+0943: "ृ" DEVANAGARI VOWEL SIGN VOCALIC R
- U+0944: "ॄ" DEVANAGARI VOWEL SIGN VOCALIC RR -->
- <Key
- latin:keyLabel="&#x0943;"
- latin:moreKeys="&#x0944;"
- latin:keyLabelFlags="fontNormal" />
+ <!-- Because the font rendering system prior to API version 16 can't automatically
+ render dotted circle for incomplete combining letter of Hindi, different set of
+ Key definitions are needed based on the API version. -->
+ <include
+ latin:keyboardLayout="@xml/key_hindi3_shift_right" />
<!-- U+091E: "ञ" DEVANAGARI LETTER NYA -->
<Key
latin:keyLabel="&#x091E;"
latin:keyLabelFlags="fontNormal" />
</case>
<default>
- <!-- U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O -->
- <Key
- latin:keyLabel="&#x0949;"
- latin:keyLabelFlags="fontNormal" />
- <!-- U+0902: "ं" DEVANAGARI SIGN ANUSVARA -->
- <Key
- latin:keyLabel="&#x0902;"
- latin:keyLabelFlags="fontNormal" />
+ <!-- Because the font rendering system prior to API version 16 can't automatically
+ render dotted circle for incomplete combining letter of Hindi, different set of
+ Key definitions are needed based on the API version. -->
+ <include
+ latin:keyboardLayout="@xml/keys_hindi3_left2" />
<!-- U+092E: "म" DEVANAGARI LETTER MA
U+0950: "ॐ" DEVANAGARI OM -->
<Key
@@ -111,14 +106,11 @@
latin:keyLabel="&#x092F;"
latin:moreKeys="&#x095F;"
latin:keyLabelFlags="fontNormal" />
- <!-- U+093C: "़" DEVANAGARI SIGN NUKTA
- U+097D: "ॽ" DEVANAGARI LETTER GLOTTAL STOP
- U+0970: "॰" DEVANAGARI ABBREVIATION SIGN
- U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA -->
- <Key
- latin:keyLabel="&#x093C;"
- latin:moreKeys="&#x097D;,&#x0970;,&#x093D;"
- latin:keyLabelFlags="fontNormal" />
+ <!-- Because the font rendering system prior to API version 16 can't automatically
+ render dotted circle for incomplete combining letter of Hindi, different set of
+ Key definitions are needed based on the API version. -->
+ <include
+ latin:keyboardLayout="@xml/key_hindi3_right" />
</default>
</switch>
</merge>
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index bf1cea9c3..ee52de1d1 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -80,16 +80,24 @@ public final class AccessibilityUtils {
}
/**
+ * Returns {@code true} if accessibility is enabled. Currently, this means
+ * that the kill switch is off and system accessibility is turned on.
+ *
+ * @return {@code true} if accessibility is enabled.
+ */
+ public boolean isAccessibilityEnabled() {
+ return ENABLE_ACCESSIBILITY && mAccessibilityManager.isEnabled();
+ }
+
+ /**
* Returns {@code true} if touch exploration is enabled. Currently, this
* means that the kill switch is off, the device supports touch exploration,
- * and a spoken feedback service is turned on.
+ * and system accessibility is turned on.
*
* @return {@code true} if touch exploration is enabled.
*/
public boolean isTouchExplorationEnabled() {
- return ENABLE_ACCESSIBILITY
- && mAccessibilityManager.isEnabled()
- && mAccessibilityManager.isTouchExplorationEnabled();
+ return isAccessibilityEnabled() && mAccessibilityManager.isTouchExplorationEnabled();
}
/**
@@ -113,6 +121,7 @@ public final class AccessibilityUtils {
*
* @return {@code true} if the device should obscure password characters.
*/
+ @SuppressWarnings("deprecation")
public boolean shouldObscureInput(final EditorInfo editorInfo) {
if (editorInfo == null) return false;
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index d05fd9eb5..e6b44120f 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -22,8 +22,11 @@ import android.support.v4.view.AccessibilityDelegateCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.util.SparseIntArray;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
@@ -35,6 +38,21 @@ import com.android.inputmethod.latin.R;
public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat {
private static final AccessibleKeyboardViewProxy sInstance = new AccessibleKeyboardViewProxy();
+ /** Map of keyboard modes to resource IDs. */
+ private static final SparseIntArray KEYBOARD_MODE_RES_IDS = new SparseIntArray();
+
+ static {
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_DATE, R.string.keyboard_mode_date);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_DATETIME, R.string.keyboard_mode_date_time);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_EMAIL, R.string.keyboard_mode_email);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_IM, R.string.keyboard_mode_im);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_NUMBER, R.string.keyboard_mode_number);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_PHONE, R.string.keyboard_mode_phone);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_TEXT, R.string.keyboard_mode_text);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_TIME, R.string.keyboard_mode_time);
+ KEYBOARD_MODE_RES_IDS.put(KeyboardId.MODE_URL, R.string.keyboard_mode_url);
+ }
+
private InputMethodService mInputMethod;
private MainKeyboardView mView;
private AccessibilityEntityProvider mAccessibilityNodeProvider;
@@ -85,11 +103,75 @@ public final class AccessibleKeyboardViewProxy extends AccessibilityDelegateComp
mAccessibilityNodeProvider.setView(view);
}
+ /**
+ * Called when the keyboard layout changes.
+ * <p>
+ * <b>Note:</b> This method will be called even if accessibility is not
+ * enabled.
+ */
public void setKeyboard() {
- if (mAccessibilityNodeProvider == null) {
+ if (mAccessibilityNodeProvider != null) {
+ mAccessibilityNodeProvider.setKeyboard();
+ }
+
+ // Since this method is called even when accessibility is off, make sure
+ // to check the state before announcing anything.
+ if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
+ announceKeyboardMode();
+ }
+ }
+
+ /**
+ * Called when the keyboard is hidden and accessibility is enabled.
+ */
+ public void onHideWindow() {
+ announceKeyboardHidden();
+ }
+
+ /**
+ * Announces which type of keyboard is being displayed. If the keyboard type
+ * is unknown, no announcement is made.
+ */
+ private void announceKeyboardMode() {
+ final Keyboard keyboard = mView.getKeyboard();
+ final int resId = KEYBOARD_MODE_RES_IDS.get(keyboard.mId.mMode);
+ if (resId == 0) {
return;
}
- mAccessibilityNodeProvider.setKeyboard();
+
+ final Context context = mView.getContext();
+ final String keyboardMode = context.getString(resId);
+ final String text = context.getString(R.string.announce_keyboard_mode, keyboardMode);
+
+ sendWindowStateChanged(text);
+ }
+
+ /**
+ * Announces that the keyboard has been hidden.
+ */
+ private void announceKeyboardHidden() {
+ final Context context = mView.getContext();
+ final String text = context.getString(R.string.announce_keyboard_hidden);
+
+ sendWindowStateChanged(text);
+ }
+
+ /**
+ * Sends a window state change event with the specified text.
+ *
+ * @param text
+ */
+ private void sendWindowStateChanged(final String text) {
+ final AccessibilityEvent stateChange = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ mView.onInitializeAccessibilityEvent(stateChange);
+ stateChange.getText().add(text);
+ stateChange.setContentDescription(null);
+
+ final ViewParent parent = mView.getParent();
+ if (parent != null) {
+ parent.requestSendAccessibilityEvent(mView, stateChange);
+ }
}
/**
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index ea86d98cb..05d8269b7 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -110,7 +110,9 @@ public final class KeyCodeDescriptionMapper {
return getDescriptionForShiftKey(context, keyboard);
}
- if (code == Constants.CODE_ACTION_ENTER) {
+ if (code == Constants.CODE_ENTER) {
+ // The following function returns the correct description in all action and
+ // regular enter cases, taking care of all modes.
return getDescriptionForActionKey(context, keyboard, key);
}
diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java
index 5a2b6bd2b..660029baf 100644
--- a/java/src/com/android/inputmethod/compat/CompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/CompatUtils.java
@@ -81,7 +81,7 @@ public final class CompatUtils {
try {
return constructor.newInstance(args);
} catch (Exception e) {
- Log.e(TAG, "Exception in newInstance: " + e.getClass().getSimpleName());
+ Log.e(TAG, "Exception in newInstance", e);
}
return null;
}
@@ -92,7 +92,7 @@ public final class CompatUtils {
try {
return method.invoke(receiver, args);
} catch (Exception e) {
- Log.e(TAG, "Exception in invoke: " + e.getClass().getSimpleName());
+ Log.e(TAG, "Exception in invoke", e);
}
return defaultValue;
}
@@ -103,7 +103,7 @@ public final class CompatUtils {
try {
return field.get(receiver);
} catch (Exception e) {
- Log.e(TAG, "Exception in getFieldValue: " + e.getClass().getSimpleName());
+ Log.e(TAG, "Exception in getFieldValue", e);
}
return defaultValue;
}
@@ -113,7 +113,7 @@ public final class CompatUtils {
try {
field.set(receiver, value);
} catch (Exception e) {
- Log.e(TAG, "Exception in setFieldValue: " + e.getClass().getSimpleName());
+ Log.e(TAG, "Exception in setFieldValue", e);
}
}
}
diff --git a/java/src/com/android/inputmethod/compat/IntentCompatUtils.java b/java/src/com/android/inputmethod/compat/IntentCompatUtils.java
new file mode 100644
index 000000000..df2e22fe8
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/IntentCompatUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 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.compat;
+
+import android.content.Intent;
+
+public final class IntentCompatUtils {
+ // Note that Intent.ACTION_USER_INITIALIZE have been introduced in API level 17
+ // (Build.VERSION_CODE.JELLY_BEAN_MR1).
+ public static final String ACTION_USER_INITIALIZE =
+ (String)CompatUtils.getFieldValue(null, null,
+ CompatUtils.getField(Intent.class, "ACTION_USER_INITIALIZE"));
+
+ private IntentCompatUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static boolean has_ACTION_USER_INITIALIZE(final Intent intent) {
+ return ACTION_USER_INITIALIZE != null && intent != null
+ && ACTION_USER_INITIALIZE.equals(intent.getAction());
+ }
+}
diff --git a/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
new file mode 100644
index 000000000..d4f1ea830
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 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.compat;
+
+import android.graphics.drawable.Drawable;
+import android.widget.TextView;
+
+import java.lang.reflect.Method;
+
+public final class TextViewCompatUtils {
+ // Note that TextView.setCompoundDrawablesRelative(Drawable,Drawable,Drawable,Drawable) has
+ // been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
+ private static final Method METHOD_setCompoundDrawablesRelative = CompatUtils.getMethod(
+ TextView.class, "setCompoundDrawablesRelative",
+ Drawable.class, Drawable.class, Drawable.class, Drawable.class);
+
+ private TextViewCompatUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static void setCompoundDrawablesRelative(final TextView textView, final Drawable start,
+ final Drawable top, final Drawable end, final Drawable bottom) {
+ if (METHOD_setCompoundDrawablesRelative == null) {
+ textView.setCompoundDrawables(start, top, end, bottom);
+ return;
+ }
+ CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelative,
+ start, top, end, bottom);
+ }
+}
diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
new file mode 100644
index 000000000..a8fab8855
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 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.compat;
+
+import android.view.View;
+
+import java.lang.reflect.Method;
+
+public final class ViewCompatUtils {
+ // Note that View.LAYOUT_DIRECTION_LTR and View.LAYOUT_DIRECTION_RTL have been introduced in
+ // API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1).
+ public static final int LAYOUT_DIRECTION_LTR = (Integer)CompatUtils.getFieldValue(null, 0x0,
+ CompatUtils.getField(View.class, "LAYOUT_DIRECTION_LTR"));
+ public static final int LAYOUT_DIRECTION_RTL = (Integer)CompatUtils.getFieldValue(null, 0x1,
+ CompatUtils.getField(View.class, "LAYOUT_DIRECTION_RTL"));
+
+ // Note that View.getPaddingEnd(), View.setPaddingRelative(int,int,int,int), and
+ // View.getLayoutDirection() have been introduced in API level 17
+ // (Build.VERSION_CODE.JELLY_BEAN_MR1).
+ private static final Method METHOD_getPaddingEnd = CompatUtils.getMethod(
+ View.class, "getPaddingEnd");
+ private static final Method METHOD_setPaddingRelative = CompatUtils.getMethod(
+ View.class, "setPaddingRelative",
+ Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE);
+ private static final Method METHOD_getLayoutDirection = CompatUtils.getMethod(
+ View.class, "getLayoutDirection");
+
+ private ViewCompatUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ public static int getPaddingEnd(final View view) {
+ if (METHOD_getPaddingEnd == null) {
+ return view.getPaddingRight();
+ }
+ return (Integer)CompatUtils.invoke(view, 0, METHOD_getPaddingEnd);
+ }
+
+ public static void setPaddingRelative(final View view, final int start, final int top,
+ final int end, final int bottom) {
+ if (METHOD_setPaddingRelative == null) {
+ view.setPadding(start, top, end, bottom);
+ return;
+ }
+ CompatUtils.invoke(view, null, METHOD_setPaddingRelative, start, top, end, bottom);
+ }
+
+ public static int getLayoutDirection(final View view) {
+ if (METHOD_getLayoutDirection == null) {
+ return LAYOUT_DIRECTION_LTR;
+ }
+ return (Integer)CompatUtils.invoke(view, 0, METHOD_getLayoutDirection);
+ }
+}
diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
index a2463c20c..720d07433 100644
--- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
+++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
@@ -58,11 +58,11 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
}
if (KeyEvent.KEYCODE_ENTER == keyCode) {
// The Enter key. If the Shift key is not being pressed, this should send a
- // CODE_ACTION_ENTER to trigger the action if any, or a carriage return
- // otherwise. If the Shift key is depressed, this should send a
- // CODE_SHIFT_ENTER and let Latin IME decide what to do with it.
+ // CODE_ENTER to trigger the action if any, or a carriage return otherwise. If the
+ // Shift key is being pressed, this should send a CODE_SHIFT_ENTER and let
+ // Latin IME decide what to do with it.
return Event.createCommittableEvent(keyEvent.isShiftPressed()
- ? Constants.CODE_SHIFT_ENTER : Constants.CODE_ACTION_ENTER,
+ ? Constants.CODE_SHIFT_ENTER : Constants.CODE_ENTER,
null /* next */);
}
// If not Enter, then we have a committable character. This should be committed
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 1e5af5154..d160038ad 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -519,11 +519,11 @@ public class Key implements Comparable<Key> {
// TODO: Handle "bold" here too?
if ((mLabelFlags & LABEL_FLAGS_FONT_NORMAL) != 0) {
return Typeface.DEFAULT;
- } else if ((mLabelFlags & LABEL_FLAGS_FONT_MONO_SPACE) != 0) {
+ }
+ if ((mLabelFlags & LABEL_FLAGS_FONT_MONO_SPACE) != 0) {
return Typeface.MONOSPACE;
- } else {
- return params.mTypeface;
}
+ return params.mTypeface;
}
public final int selectTextSize(final KeyDrawParams params) {
@@ -550,28 +550,51 @@ public class Key implements Comparable<Key> {
public final int selectHintTextSize(final KeyDrawParams params) {
if (hasHintLabel()) {
return params.mHintLabelSize;
- } else if (hasShiftedLetterHint()) {
+ }
+ if (hasShiftedLetterHint()) {
return params.mShiftedLetterHintSize;
- } else {
- return params.mHintLetterSize;
}
+ return params.mHintLetterSize;
}
public final int selectHintTextColor(final KeyDrawParams params) {
if (hasHintLabel()) {
return params.mHintLabelColor;
- } else if (hasShiftedLetterHint()) {
+ }
+ if (hasShiftedLetterHint()) {
return isShiftedLetterActivated() ? params.mShiftedLetterHintActivatedColor
: params.mShiftedLetterHintInactivatedColor;
- } else {
- return params.mHintLetterColor;
}
+ return params.mHintLetterColor;
}
public final int selectMoreKeyTextSize(final KeyDrawParams params) {
return hasLabelsInMoreKeys() ? params.mLabelSize : params.mLetterSize;
}
+ public final String getPreviewLabel() {
+ return isShiftedLetterActivated() ? mHintLabel : mLabel;
+ }
+
+ private boolean previewHasLetterSize() {
+ return (mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO) != 0
+ || StringUtils.codePointCount(getPreviewLabel()) == 1;
+ }
+
+ public final int selectPreviewTextSize(final KeyDrawParams params) {
+ if (previewHasLetterSize()) {
+ return params.mPreviewTextSize;
+ }
+ return params.mLetterSize;
+ }
+
+ public Typeface selectPreviewTypeface(final KeyDrawParams params) {
+ if (previewHasLetterSize()) {
+ return selectTypeface(params);
+ }
+ return Typeface.DEFAULT_BOLD;
+ }
+
public final boolean isAlignLeft() {
return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT) != 0;
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 4dab50fd8..350dc69b2 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -635,15 +635,9 @@ public class KeyboardView extends View {
invalidate(x, y, x + key.mWidth, y + key.mHeight);
}
- public void closing() {
- mInvalidateAllKeys = true;
- mKeyboard = null;
- }
-
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- closing();
freeOffscreenBuffer();
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 4d10f0e69..d37b69b00 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -811,18 +811,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
background.setState(KEY_PREVIEW_BACKGROUND_DEFAULT_STATE);
background.setAlpha(PREVIEW_ALPHA);
}
- final String label = key.isShiftedLetterActivated() ? key.mHintLabel : key.mLabel;
+ final String label = key.getPreviewLabel();
// What we show as preview should match what we show on a key top in onDraw().
if (label != null) {
// TODO Should take care of temporaryShiftLabel here.
previewText.setCompoundDrawables(null, null, null, null);
- if (StringUtils.codePointCount(label) > 1) {
- previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, drawParams.mLetterSize);
- previewText.setTypeface(Typeface.DEFAULT_BOLD);
- } else {
- previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, drawParams.mPreviewTextSize);
- previewText.setTypeface(key.selectTypeface(drawParams));
- }
+ previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ key.selectPreviewTextSize(drawParams));
+ previewText.setTypeface(key.selectPreviewTypeface(drawParams));
previewText.setText(label);
} else {
previewText.setCompoundDrawables(null, null, null,
@@ -1236,13 +1232,11 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
mDrawingHandler.cancelAllMessages();
}
- @Override
public void closing() {
dismissAllKeyPreviews();
cancelAllMessages();
onDismissMoreKeysPanel();
mMoreKeysKeyboardCache.clear();
- super.closing();
}
/**
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
index 9e75f8b8a..0d42ab2fe 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
@@ -174,7 +174,6 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
@Override
public boolean dismissMoreKeysPanel() {
- super.closing();
if (mController == null) return false;
return mController.onDismissMoreKeysPanel();
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
index 0ec6b0176..3e25c3b86 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -48,7 +48,6 @@ public final class KeyboardCodesSet {
"key_delete",
"key_settings",
"key_shortcut",
- "key_action_enter",
"key_action_next",
"key_action_previous",
"key_shift_enter",
@@ -85,7 +84,6 @@ public final class KeyboardCodesSet {
Constants.CODE_DELETE,
Constants.CODE_SETTINGS,
Constants.CODE_SHORTCUT,
- Constants.CODE_ACTION_ENTER,
Constants.CODE_ACTION_NEXT,
Constants.CODE_ACTION_PREVIOUS,
Constants.CODE_SHIFT_ENTER,
@@ -118,7 +116,6 @@ public final class KeyboardCodesSet {
DEFAULT[12],
DEFAULT[13],
DEFAULT[14],
- DEFAULT[15],
CODE_RIGHT_PARENTHESIS,
CODE_LEFT_PARENTHESIS,
CODE_GREATER_THAN_SIGN,
@@ -142,7 +139,7 @@ public final class KeyboardCodesSet {
};
static {
- if (DEFAULT.length != RTL.length) {
+ if (DEFAULT.length != RTL.length || DEFAULT.length != ID_TO_NAME.length) {
throw new RuntimeException("Internal inconsistency");
}
for (int i = 0; i < ID_TO_NAME.length; i++) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index 493093e95..d0b382e35 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -145,94 +145,110 @@ public final class KeyboardTextsSet {
/* 40 */ "more_keys_for_cyrillic_ie",
/* 41 */ "more_keys_for_cyrillic_i",
/* 42 */ "label_to_alpha_key",
- /* 43 */ "more_keys_for_single_quote",
- /* 44 */ "more_keys_for_double_quote",
- /* 45 */ "more_keys_for_tablet_double_quote",
- /* 46 */ "more_keys_for_currency_dollar",
- /* 47 */ "keylabel_for_currency_generic",
- /* 48 */ "more_keys_for_currency_generic",
- /* 49 */ "more_keys_for_punctuation",
- /* 50 */ "more_keys_for_star",
- /* 51 */ "more_keys_for_bullet",
- /* 52 */ "more_keys_for_plus",
- /* 53 */ "more_keys_for_left_parenthesis",
- /* 54 */ "more_keys_for_right_parenthesis",
- /* 55 */ "more_keys_for_less_than",
- /* 56 */ "more_keys_for_greater_than",
- /* 57 */ "more_keys_for_arabic_diacritics",
- /* 58 */ "keyhintlabel_for_arabic_diacritics",
- /* 59 */ "keylabel_for_symbols_1",
- /* 60 */ "keylabel_for_symbols_2",
- /* 61 */ "keylabel_for_symbols_3",
- /* 62 */ "keylabel_for_symbols_4",
- /* 63 */ "keylabel_for_symbols_5",
- /* 64 */ "keylabel_for_symbols_6",
- /* 65 */ "keylabel_for_symbols_7",
- /* 66 */ "keylabel_for_symbols_8",
- /* 67 */ "keylabel_for_symbols_9",
- /* 68 */ "keylabel_for_symbols_0",
- /* 69 */ "label_to_symbol_key",
- /* 70 */ "label_to_symbol_with_microphone_key",
- /* 71 */ "additional_more_keys_for_symbols_1",
- /* 72 */ "additional_more_keys_for_symbols_2",
- /* 73 */ "additional_more_keys_for_symbols_3",
- /* 74 */ "additional_more_keys_for_symbols_4",
- /* 75 */ "additional_more_keys_for_symbols_5",
- /* 76 */ "additional_more_keys_for_symbols_6",
- /* 77 */ "additional_more_keys_for_symbols_7",
- /* 78 */ "additional_more_keys_for_symbols_8",
- /* 79 */ "additional_more_keys_for_symbols_9",
- /* 80 */ "additional_more_keys_for_symbols_0",
- /* 81 */ "more_keys_for_symbols_1",
- /* 82 */ "more_keys_for_symbols_2",
- /* 83 */ "more_keys_for_symbols_3",
- /* 84 */ "more_keys_for_symbols_4",
- /* 85 */ "more_keys_for_symbols_5",
- /* 86 */ "more_keys_for_symbols_6",
- /* 87 */ "more_keys_for_symbols_7",
- /* 88 */ "more_keys_for_symbols_8",
- /* 89 */ "more_keys_for_symbols_9",
- /* 90 */ "more_keys_for_symbols_0",
- /* 91 */ "keylabel_for_comma",
- /* 92 */ "more_keys_for_comma",
- /* 93 */ "keylabel_for_symbols_question",
- /* 94 */ "keylabel_for_symbols_semicolon",
- /* 95 */ "keylabel_for_symbols_percent",
- /* 96 */ "more_keys_for_symbols_exclamation",
- /* 97 */ "more_keys_for_symbols_question",
- /* 98 */ "more_keys_for_symbols_semicolon",
- /* 99 */ "more_keys_for_symbols_percent",
- /* 100 */ "keylabel_for_tablet_comma",
- /* 101 */ "keyhintlabel_for_tablet_comma",
- /* 102 */ "more_keys_for_tablet_comma",
- /* 103 */ "keyhintlabel_for_tablet_period",
- /* 104 */ "more_keys_for_tablet_period",
- /* 105 */ "keylabel_for_apostrophe",
- /* 106 */ "keyhintlabel_for_apostrophe",
- /* 107 */ "more_keys_for_apostrophe",
- /* 108 */ "more_keys_for_q",
- /* 109 */ "more_keys_for_x",
- /* 110 */ "keylabel_for_q",
- /* 111 */ "keylabel_for_w",
- /* 112 */ "keylabel_for_y",
- /* 113 */ "keylabel_for_x",
- /* 114 */ "keylabel_for_spanish_row2_10",
- /* 115 */ "more_keys_for_am_pm",
- /* 116 */ "settings_as_more_key",
- /* 117 */ "shortcut_as_more_key",
- /* 118 */ "action_next_as_more_key",
- /* 119 */ "action_previous_as_more_key",
- /* 120 */ "label_to_more_symbol_key",
- /* 121 */ "label_to_more_symbol_for_tablet_key",
- /* 122 */ "label_tab_key",
- /* 123 */ "label_to_phone_numeric_key",
- /* 124 */ "label_to_phone_symbols_key",
- /* 125 */ "label_time_am",
- /* 126 */ "label_time_pm",
- /* 127 */ "label_to_symbol_key_pcqwerty",
- /* 128 */ "keylabel_for_popular_domain",
- /* 129 */ "more_keys_for_popular_domain",
- /* 130 */ "more_keys_for_smiley",
+ /* 43 */ "single_quotes",
+ /* 44 */ "double_quotes",
+ /* 45 */ "single_angle_quotes",
+ /* 46 */ "double_angle_quotes",
+ /* 47 */ "more_keys_for_currency_dollar",
+ /* 48 */ "keylabel_for_currency_generic",
+ /* 49 */ "more_keys_for_currency_generic",
+ /* 50 */ "more_keys_for_punctuation",
+ /* 51 */ "more_keys_for_star",
+ /* 52 */ "more_keys_for_bullet",
+ /* 53 */ "more_keys_for_plus",
+ /* 54 */ "more_keys_for_left_parenthesis",
+ /* 55 */ "more_keys_for_right_parenthesis",
+ /* 56 */ "more_keys_for_less_than",
+ /* 57 */ "more_keys_for_greater_than",
+ /* 58 */ "more_keys_for_arabic_diacritics",
+ /* 59 */ "keyhintlabel_for_arabic_diacritics",
+ /* 60 */ "keylabel_for_symbols_1",
+ /* 61 */ "keylabel_for_symbols_2",
+ /* 62 */ "keylabel_for_symbols_3",
+ /* 63 */ "keylabel_for_symbols_4",
+ /* 64 */ "keylabel_for_symbols_5",
+ /* 65 */ "keylabel_for_symbols_6",
+ /* 66 */ "keylabel_for_symbols_7",
+ /* 67 */ "keylabel_for_symbols_8",
+ /* 68 */ "keylabel_for_symbols_9",
+ /* 69 */ "keylabel_for_symbols_0",
+ /* 70 */ "label_to_symbol_key",
+ /* 71 */ "label_to_symbol_with_microphone_key",
+ /* 72 */ "additional_more_keys_for_symbols_1",
+ /* 73 */ "additional_more_keys_for_symbols_2",
+ /* 74 */ "additional_more_keys_for_symbols_3",
+ /* 75 */ "additional_more_keys_for_symbols_4",
+ /* 76 */ "additional_more_keys_for_symbols_5",
+ /* 77 */ "additional_more_keys_for_symbols_6",
+ /* 78 */ "additional_more_keys_for_symbols_7",
+ /* 79 */ "additional_more_keys_for_symbols_8",
+ /* 80 */ "additional_more_keys_for_symbols_9",
+ /* 81 */ "additional_more_keys_for_symbols_0",
+ /* 82 */ "more_keys_for_symbols_1",
+ /* 83 */ "more_keys_for_symbols_2",
+ /* 84 */ "more_keys_for_symbols_3",
+ /* 85 */ "more_keys_for_symbols_4",
+ /* 86 */ "more_keys_for_symbols_5",
+ /* 87 */ "more_keys_for_symbols_6",
+ /* 88 */ "more_keys_for_symbols_7",
+ /* 89 */ "more_keys_for_symbols_8",
+ /* 90 */ "more_keys_for_symbols_9",
+ /* 91 */ "more_keys_for_symbols_0",
+ /* 92 */ "keylabel_for_comma",
+ /* 93 */ "more_keys_for_comma",
+ /* 94 */ "keylabel_for_symbols_question",
+ /* 95 */ "keylabel_for_symbols_semicolon",
+ /* 96 */ "keylabel_for_symbols_percent",
+ /* 97 */ "more_keys_for_symbols_exclamation",
+ /* 98 */ "more_keys_for_symbols_question",
+ /* 99 */ "more_keys_for_symbols_semicolon",
+ /* 100 */ "more_keys_for_symbols_percent",
+ /* 101 */ "keylabel_for_tablet_comma",
+ /* 102 */ "keyhintlabel_for_tablet_comma",
+ /* 103 */ "more_keys_for_tablet_comma",
+ /* 104 */ "keyhintlabel_for_tablet_period",
+ /* 105 */ "more_keys_for_tablet_period",
+ /* 106 */ "keylabel_for_apostrophe",
+ /* 107 */ "keyhintlabel_for_apostrophe",
+ /* 108 */ "more_keys_for_apostrophe",
+ /* 109 */ "more_keys_for_q",
+ /* 110 */ "more_keys_for_x",
+ /* 111 */ "keylabel_for_q",
+ /* 112 */ "keylabel_for_w",
+ /* 113 */ "keylabel_for_y",
+ /* 114 */ "keylabel_for_x",
+ /* 115 */ "keylabel_for_spanish_row2_10",
+ /* 116 */ "more_keys_for_am_pm",
+ /* 117 */ "settings_as_more_key",
+ /* 118 */ "shortcut_as_more_key",
+ /* 119 */ "action_next_as_more_key",
+ /* 120 */ "action_previous_as_more_key",
+ /* 121 */ "label_to_more_symbol_key",
+ /* 122 */ "label_to_more_symbol_for_tablet_key",
+ /* 123 */ "label_tab_key",
+ /* 124 */ "label_to_phone_numeric_key",
+ /* 125 */ "label_to_phone_symbols_key",
+ /* 126 */ "label_time_am",
+ /* 127 */ "label_time_pm",
+ /* 128 */ "label_to_symbol_key_pcqwerty",
+ /* 129 */ "keylabel_for_popular_domain",
+ /* 130 */ "more_keys_for_popular_domain",
+ /* 131 */ "more_keys_for_smiley",
+ /* 132 */ "single_laqm_raqm",
+ /* 133 */ "single_laqm_raqm_rtl",
+ /* 134 */ "single_raqm_laqm",
+ /* 135 */ "double_laqm_raqm",
+ /* 136 */ "double_laqm_raqm_rtl",
+ /* 137 */ "double_raqm_laqm",
+ /* 138 */ "single_lqm_rqm",
+ /* 139 */ "single_9qm_lqm",
+ /* 140 */ "single_9qm_rqm",
+ /* 141 */ "double_lqm_rqm",
+ /* 142 */ "double_9qm_lqm",
+ /* 143 */ "double_9qm_rqm",
+ /* 144 */ "more_keys_for_single_quote",
+ /* 145 */ "more_keys_for_double_quote",
+ /* 146 */ "more_keys_for_tablet_double_quote",
};
private static final String EMPTY = "";
@@ -247,155 +263,182 @@ public final class KeyboardTextsSet {
/* ~41 */
// Label for "switch to alphabetic" key.
/* 42 */ "ABC",
- /* 43 */ "!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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;</string>
- /* 44 */ "!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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- /* 45 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
+ /* 43 */ "!text/single_lqm_rqm",
+ /* 44 */ "!text/double_lqm_rqm",
+ /* 45 */ "!text/single_laqm_raqm",
+ /* 46 */ "!text/double_laqm_raqm",
// U+00A2: "¢" CENT SIGN
// U+00A3: "£" POUND SIGN
// U+20AC: "€" EURO SIGN
// U+00A5: "¥" YEN SIGN
// U+20B1: "₱" PESO SIGN
- /* 46 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
- /* 47 */ "$",
- /* 48 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1",
- /* 49 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\\,,?,@,&,\\%,+,;,/,(,)",
+ /* 47 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
+ /* 48 */ "$",
+ /* 49 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1",
+ /* 50 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\\,,?,@,&,\\%,+,;,/,(,)",
// U+2020: "†" DAGGER
// U+2021: "‡" DOUBLE DAGGER
// U+2605: "★" BLACK STAR
- /* 50 */ "\u2020,\u2021,\u2605",
+ /* 51 */ "\u2020,\u2021,\u2605",
// U+266A: "♪" EIGHTH NOTE
// U+2665: "♥" BLACK HEART SUIT
// U+2660: "♠" BLACK SPADE SUIT
// U+2666: "♦" BLACK DIAMOND SUIT
// U+2663: "♣" BLACK CLUB SUIT
- /* 51 */ "\u266A,\u2665,\u2660,\u2666,\u2663",
+ /* 52 */ "\u266A,\u2665,\u2660,\u2666,\u2663",
// U+00B1: "±" PLUS-MINUS SIGN
- /* 52 */ "\u00B1",
+ /* 53 */ "\u00B1",
// The all letters need to be mirrored are found at
// http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
- /* 53 */ "!fixedColumnOrder!3,<,{,[",
- /* 54 */ "!fixedColumnOrder!3,>,},]",
+ /* 54 */ "!fixedColumnOrder!3,<,{,[",
+ /* 55 */ "!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
- /* 55 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB",
- /* 56 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB",
- /* 57 */ EMPTY,
+ /* 56 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB",
+ /* 57 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB",
/* 58 */ EMPTY,
- /* 59 */ "1",
- /* 60 */ "2",
- /* 61 */ "3",
- /* 62 */ "4",
- /* 63 */ "5",
- /* 64 */ "6",
- /* 65 */ "7",
- /* 66 */ "8",
- /* 67 */ "9",
- /* 68 */ "0",
+ /* 59 */ EMPTY,
+ /* 60 */ "1",
+ /* 61 */ "2",
+ /* 62 */ "3",
+ /* 63 */ "4",
+ /* 64 */ "5",
+ /* 65 */ "6",
+ /* 66 */ "7",
+ /* 67 */ "8",
+ /* 68 */ "9",
+ /* 69 */ "0",
// Label for "switch to symbols" key.
- /* 69 */ "?123",
+ /* 70 */ "?123",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 70 */ "123",
- /* 71~ */
+ /* 71 */ "123",
+ /* 72~ */
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
- /* ~80 */
+ /* ~81 */
// 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
- /* 81 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B",
+ /* 82 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B",
// U+00B2: "²" SUPERSCRIPT TWO
// U+2154: "⅔" VULGAR FRACTION TWO THIRDS
- /* 82 */ "\u00B2,\u2154",
+ /* 83 */ "\u00B2,\u2154",
// U+00B3: "³" SUPERSCRIPT THREE
// U+00BE: "¾" VULGAR FRACTION THREE QUARTERS
// U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS
- /* 83 */ "\u00B3,\u00BE,\u215C",
+ /* 84 */ "\u00B3,\u00BE,\u215C",
// U+2074: "⁴" SUPERSCRIPT FOUR
- /* 84 */ "\u2074",
+ /* 85 */ "\u2074",
// U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS
- /* 85 */ "\u215D",
- /* 86 */ EMPTY,
+ /* 86 */ "\u215D",
+ /* 87 */ EMPTY,
// U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS
- /* 87 */ "\u215E",
- /* 88 */ EMPTY,
+ /* 88 */ "\u215E",
/* 89 */ EMPTY,
+ /* 90 */ EMPTY,
// U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N
// U+2205: "∅" EMPTY SET
- /* 90 */ "\u207F,\u2205",
- /* 91 */ ",",
- /* 92 */ EMPTY,
- /* 93 */ "?",
- /* 94 */ ";",
- /* 95 */ "%",
+ /* 91 */ "\u207F,\u2205",
+ /* 92 */ ",",
+ /* 93 */ EMPTY,
+ /* 94 */ "?",
+ /* 95 */ ";",
+ /* 96 */ "%",
// U+00A1: "¡" INVERTED EXCLAMATION MARK
- /* 96 */ "\u00A1",
+ /* 97 */ "\u00A1",
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 97 */ "\u00BF",
- /* 98 */ EMPTY,
+ /* 98 */ "\u00BF",
+ /* 99 */ EMPTY,
// U+2030: "‰" PER MILLE SIGN
- /* 99 */ "\u2030",
- /* 100 */ ",",
- /* 101 */ "!",
+ /* 100 */ "\u2030",
+ /* 101 */ ",",
/* 102 */ "!",
- /* 103 */ "?",
+ /* 103 */ "!",
/* 104 */ "?",
- /* 105 */ "\'",
- /* 106 */ "\"",
+ /* 105 */ "?",
+ /* 106 */ "\'",
/* 107 */ "\"",
- /* 108 */ EMPTY,
+ /* 108 */ "\"",
/* 109 */ EMPTY,
- /* 110 */ "q",
- /* 111 */ "w",
- /* 112 */ "y",
- /* 113 */ "x",
+ /* 110 */ EMPTY,
+ /* 111 */ "q",
+ /* 112 */ "w",
+ /* 113 */ "y",
+ /* 114 */ "x",
// U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
- /* 114 */ "\u00F1",
- /* 115 */ "!fixedColumnOrder!2,!hasLabels!,!text/label_time_am,!text/label_time_pm",
- /* 116 */ "!icon/settings_key|!code/key_settings",
- /* 117 */ "!icon/shortcut_key|!code/key_shortcut",
- /* 118 */ "!hasLabels!,!text/label_next_key|!code/key_action_next",
- /* 119 */ "!hasLabels!,!text/label_previous_key|!code/key_action_previous",
+ /* 115 */ "\u00F1",
+ /* 116 */ "!fixedColumnOrder!2,!hasLabels!,!text/label_time_am,!text/label_time_pm",
+ /* 117 */ "!icon/settings_key|!code/key_settings",
+ /* 118 */ "!icon/shortcut_key|!code/key_shortcut",
+ /* 119 */ "!hasLabels!,!text/label_next_key|!code/key_action_next",
+ /* 120 */ "!hasLabels!,!text/label_previous_key|!code/key_action_previous",
// Label for "switch to more symbol" modifier key. Must be short to fit on key!
- /* 120 */ "= \\ <",
+ /* 121 */ "= \\ <",
// Label for "switch to more symbol" modifier key on tablets. Must be short to fit on key!
- /* 121 */ "~ \\ {",
+ /* 122 */ "~ \\ {",
// Label for "Tab" key. Must be short to fit on key!
- /* 122 */ "Tab",
+ /* 123 */ "Tab",
// Label for "switch to phone numeric" key. Must be short to fit on key!
- /* 123 */ "123",
+ /* 124 */ "123",
// Label for "switch to phone symbols" key. Must be short to fit on key!
// U+FF0A: "*" FULLWIDTH ASTERISK
// U+FF03: "#" FULLWIDTH NUMBER SIGN
- /* 124 */ "\uFF0A\uFF03",
+ /* 125 */ "\uFF0A\uFF03",
// Key label for "ante meridiem"
- /* 125 */ "AM",
+ /* 126 */ "AM",
// Key label for "post meridiem"
- /* 126 */ "PM",
+ /* 127 */ "PM",
// Label for "switch to symbols" key on PC QWERTY layout
- /* 127 */ "Sym",
- /* 128 */ ".com",
+ /* 128 */ "Sym",
+ /* 129 */ ".com",
// popular web domains for the locale - most popular, displayed on the keyboard
- /* 129 */ "!hasLabels!,.net,.org,.gov,.edu",
- /* 130 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ",
+ /* 130 */ "!hasLabels!,.net,.org,.gov,.edu",
+ /* 131 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ",
+ // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ // 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+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ // Abbreviations are:
+ // laqm: LEFT-POINTING ANGLE QUOTATION MARK
+ // raqm: RIGHT-POINTING ANGLE QUOTATION MARK
+ // rtl: Right-To-Left script order
+ // lqm: LEFT QUOTATION MARK
+ // rqm: RIGHT QUOTATION MARK
+ // 9qm: LOW-9 QUOTATION MARK
+ // The following each quotation mark pair consist of
+ // <opening quotation mark>, <closing quotation mark>
+ // and is named after (single|double)_<opening quotation mark>_<closing quotation mark>.
+ /* 132 */ "\u2039,\u203A",
+ /* 133 */ "\u2039|\u203A,\u203A|\u2039",
+ /* 134 */ "\u203A,\u2039",
+ /* 135 */ "\u00AB,\u00BB",
+ /* 136 */ "\u00AB|\u00BB,\u00BB|\u00AB",
+ /* 137 */ "\u00BB,\u00AB",
+ // The following each quotation mark triplet consists of
+ // <another quotation mark>, <opening quotation mark>, <closing quotation mark>
+ // and is named after (single|double)_<opening quotation mark>_<closing quotation mark>.
+ /* 138 */ "\u201A,\u2018,\u2019",
+ /* 139 */ "\u2019,\u201A,\u2018",
+ /* 140 */ "\u2018,\u201A,\u2019",
+ /* 141 */ "\u201E,\u201C,\u201D",
+ /* 142 */ "\u201D,\u201E,\u201C",
+ /* 143 */ "\u201C,\u201E,\u201D",
+ /* 144 */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes",
+ /* 145 */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes",
+ /* 146 */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes",
};
/* Language af: Afrikaans */
@@ -465,54 +508,36 @@ public final class KeyboardTextsSet {
// U+062C: "پ" ARABIC LETTER PEH
/* 42 */ "\u0623\u200C\u0628\u200C\u062C",
/* 43 */ null,
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
- /* 44 */ "!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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- /* 45 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
- // U+00A2: "¢" CENT SIGN
- // U+00A3: "£" POUND SIGN
- // U+20AC: "€" EURO SIGN
- // U+00A5: "¥" YEN SIGN
- // U+20B1: "₱" PESO SIGN
- // U+FDFC: "﷼" RIAL SIGN
- /* 46 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1,\uFDFC",
- /* 47 */ null,
- /* 48 */ null,
+ /* 44 */ null,
+ /* 45 */ "!text/single_laqm_raqm_rtl",
+ /* 46 */ "!text/double_laqm_raqm_rtl",
+ /* 47~ */
+ null, null, null,
+ /* ~49 */
// U+061F: "؟" ARABIC QUESTION MARK
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
- /* 49 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
+ /* 50 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
// U+2605: "★" BLACK STAR
// U+066D: "٭" ARABIC FIVE POINTED STAR
- /* 50 */ "\u2605,\u066D",
+ /* 51 */ "\u2605,\u066D",
// U+266A: "♪" EIGHTH NOTE
- /* 51 */ "\u266A",
- /* 52 */ null,
+ /* 52 */ "\u266A",
+ /* 53 */ 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
- /* 53 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
- /* 54 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
+ /* 54 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 55 */ "!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
- /* 55 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
- /* 56 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 56 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 57 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
// U+0655: "ٕ" ARABIC HAMZA BELOW
// U+0654: "ٔ" ARABIC HAMZA ABOVE
// U+0652: "ْ" ARABIC SUKUN
@@ -529,70 +554,70 @@ public final class KeyboardTextsSet {
// U+0640: "ـ" ARABIC TATWEEL
// In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
// Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
- /* 57 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
- /* 58 */ "\u0651",
+ /* 58 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
+ /* 59 */ "\u0651",
// U+0661: "١" ARABIC-INDIC DIGIT ONE
- /* 59 */ "\u0661",
+ /* 60 */ "\u0661",
// U+0662: "٢" ARABIC-INDIC DIGIT TWO
- /* 60 */ "\u0662",
+ /* 61 */ "\u0662",
// U+0663: "٣" ARABIC-INDIC DIGIT THREE
- /* 61 */ "\u0663",
+ /* 62 */ "\u0663",
// U+0664: "٤" ARABIC-INDIC DIGIT FOUR
- /* 62 */ "\u0664",
+ /* 63 */ "\u0664",
// U+0665: "٥" ARABIC-INDIC DIGIT FIVE
- /* 63 */ "\u0665",
+ /* 64 */ "\u0665",
// U+0666: "٦" ARABIC-INDIC DIGIT SIX
- /* 64 */ "\u0666",
+ /* 65 */ "\u0666",
// U+0667: "٧" ARABIC-INDIC DIGIT SEVEN
- /* 65 */ "\u0667",
+ /* 66 */ "\u0667",
// U+0668: "٨" ARABIC-INDIC DIGIT EIGHT
- /* 66 */ "\u0668",
+ /* 67 */ "\u0668",
// U+0669: "٩" ARABIC-INDIC DIGIT NINE
- /* 67 */ "\u0669",
+ /* 68 */ "\u0669",
// U+0660: "٠" ARABIC-INDIC DIGIT ZERO
- /* 68 */ "\u0660",
+ /* 69 */ "\u0660",
// Label for "switch to symbols" key.
// U+061F: "؟" ARABIC QUESTION MARK
- /* 69 */ "\u0663\u0662\u0661\u061F",
+ /* 70 */ "\u0663\u0662\u0661\u061F",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 70 */ "\u0663\u0662\u0661",
- /* 71 */ "1",
- /* 72 */ "2",
- /* 73 */ "3",
- /* 74 */ "4",
- /* 75 */ "5",
- /* 76 */ "6",
- /* 77 */ "7",
- /* 78 */ "8",
- /* 79 */ "9",
+ /* 71 */ "\u0663\u0662\u0661",
+ /* 72 */ "1",
+ /* 73 */ "2",
+ /* 74 */ "3",
+ /* 75 */ "4",
+ /* 76 */ "5",
+ /* 77 */ "6",
+ /* 78 */ "7",
+ /* 79 */ "8",
+ /* 80 */ "9",
// U+066B: "٫" ARABIC DECIMAL SEPARATOR
// U+066C: "٬" ARABIC THOUSANDS SEPARATOR
- /* 80 */ "0,\u066B,\u066C",
- /* 81~ */
+ /* 81 */ "0,\u066B,\u066C",
+ /* 82~ */
null, null, null, null, null, null, null, null, null, null,
- /* ~90 */
+ /* ~91 */
// U+060C: "،" ARABIC COMMA
- /* 91 */ "\u060C",
- /* 92 */ "\\,",
- /* 93 */ "\u061F",
- /* 94 */ "\u061B",
+ /* 92 */ "\u060C",
+ /* 93 */ "\\,",
+ /* 94 */ "\u061F",
+ /* 95 */ "\u061B",
// U+066A: "٪" ARABIC PERCENT SIGN
- /* 95 */ "\u066A",
- /* 96 */ null,
- /* 97 */ "?",
- /* 98 */ ";",
+ /* 96 */ "\u066A",
+ /* 97 */ null,
+ /* 98 */ "?",
+ /* 99 */ ";",
// U+2030: "‰" PER MILLE SIGN
- /* 99 */ "\\%,\u2030",
- /* 100~ */
+ /* 100 */ "\\%,\u2030",
+ /* 101~ */
null, null, null, null, null,
- /* ~104 */
+ /* ~105 */
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
// U+061F: "؟" ARABIC QUESTION MARK
- /* 105 */ "\u060C",
- /* 106 */ "\u061F",
- /* 107 */ "\u061F,\u061B,!,:,-,/,\',\"",
+ /* 106 */ "\u060C",
+ /* 107 */ "\u061F",
+ /* 108 */ "\u061F,\u061B,!,:,-,/,\',\"",
};
/* Language be: Belarusian */
@@ -627,6 +652,8 @@ public final class KeyboardTextsSet {
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
/* 42 */ "\u0410\u0411\u0412",
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language bg: Bulgarian */
@@ -641,6 +668,9 @@ public final class KeyboardTextsSet {
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
/* 42 */ "\u0410\u0411\u0412",
+ /* 43 */ null,
+ // single_quotes of Bulgarian is default single_quotes_right_left.
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language ca: Catalan */
@@ -771,6 +801,14 @@ public final class KeyboardTextsSet {
// 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, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language da: Danish */
@@ -832,6 +870,14 @@ public final class KeyboardTextsSet {
/* 23 */ "\u00E4",
// U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
/* 24 */ "\u00F6",
+ /* 25~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language de: German */
@@ -874,6 +920,15 @@ public final class KeyboardTextsSet {
// U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
// U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
/* 6 */ "\u00F1,\u0144",
+ /* 7~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language el: Greek */
@@ -1058,20 +1113,20 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~107 */
- /* 108 */ "q",
- /* 109 */ "x",
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~108 */
+ /* 109 */ "q",
+ /* 110 */ "x",
// U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX
- /* 110 */ "\u015D",
+ /* 111 */ "\u015D",
// U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX
- /* 111 */ "\u011D",
+ /* 112 */ "\u011D",
// U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE
- /* 112 */ "\u016D",
+ /* 113 */ "\u016D",
// U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX
- /* 113 */ "\u0109",
+ /* 114 */ "\u0109",
// U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
- /* 114 */ "\u0135",
+ /* 115 */ "\u0135",
};
/* Language es: Spanish */
@@ -1129,25 +1184,25 @@ public final class KeyboardTextsSet {
/* 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 */
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~49 */
// U+00A1: "¡" INVERTED EXCLAMATION MARK
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 49 */ "!fixedColumnOrder!9,\u00A1,\",\',#,-,:,!,\\,,?,\u00BF,@,&,\\%,+,;,/,(,)",
- /* 50~ */
+ /* 50 */ "!fixedColumnOrder!9,\u00A1,\",\',#,-,:,!,\\,,?,\u00BF,@,&,\\%,+,;,/,(,)",
+ /* 51~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null,
- /* ~101 */
+ /* ~102 */
// U+00A1: "¡" INVERTED EXCLAMATION MARK
- /* 102 */ "!,\u00A1",
- /* 103 */ null,
+ /* 103 */ "!,\u00A1",
+ /* 104 */ null,
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 104 */ "?,\u00BF",
- /* 105 */ "\"",
- /* 106 */ "\'",
+ /* 105 */ "?,\u00BF",
+ /* 106 */ "\"",
/* 107 */ "\'",
+ /* 108 */ "\'",
};
/* Language et: Estonian */
@@ -1248,6 +1303,12 @@ public final class KeyboardTextsSet {
/* 22 */ "\u00E4",
// U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
/* 23 */ "\u00F5",
+ /* 24~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language fa: Persian */
@@ -1264,55 +1325,36 @@ public final class KeyboardTextsSet {
// U+067E: "پ" ARABIC LETTER PEH
/* 42 */ "\u0627\u200C\u0628\u200C\u067E",
/* 43 */ null,
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
- /* 44 */ "!fixedColumnOrder!4,\u201C,\u201D,\",\'",
- // 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- /* 45 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
- /* 46 */ null,
- // U+FDFC: "﷼" RIAL SIGN
- // U+060B: "؋" AFGHANI SIGN
- // U+00A2: "¢" CENT SIGN
- // U+00A3: "£" POUND SIGN
- // U+20AC: "€" EURO SIGN
- // U+00A5: "¥" YEN SIGN
- // U+20B1: "₱" PESO SIGN
- /* 47 */ "\uFDFC",
- /* 48 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1,\u060B",
+ /* 44 */ null,
+ /* 45 */ "!text/single_laqm_raqm_rtl",
+ /* 46 */ "!text/double_laqm_raqm_rtl",
+ /* 47~ */
+ null, null, null,
+ /* ~49 */
// U+061F: "؟" ARABIC QUESTION MARK
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
- /* 49 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
+ /* 50 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
// U+2605: "★" BLACK STAR
// U+066D: "٭" ARABIC FIVE POINTED STAR
- /* 50 */ "\u2605,\u066D",
+ /* 51 */ "\u2605,\u066D",
// U+266A: "♪" EIGHTH NOTE
- /* 51 */ "\u266A",
- /* 52 */ null,
+ /* 52 */ "\u266A",
+ /* 53 */ 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
- /* 53 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
- /* 54 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
+ /* 54 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 55 */ "!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
- /* 55 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,<|>",
- /* 56 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,>|<",
+ /* 56 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,<|>",
+ /* 57 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,>|<",
// U+0655: "ٕ" ARABIC HAMZA BELOW
// U+0652: "ْ" ARABIC SUKUN
// U+0651: "ّ" ARABIC SHADDA
@@ -1329,74 +1371,74 @@ public final class KeyboardTextsSet {
// U+0640: "ـ" ARABIC TATWEEL
// In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
// Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
- /* 57 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
- /* 58 */ "\u064B",
+ /* 58 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
+ /* 59 */ "\u064B",
// U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE
- /* 59 */ "\u06F1",
+ /* 60 */ "\u06F1",
// U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO
- /* 60 */ "\u06F2",
+ /* 61 */ "\u06F2",
// U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE
- /* 61 */ "\u06F3",
+ /* 62 */ "\u06F3",
// U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR
- /* 62 */ "\u06F4",
+ /* 63 */ "\u06F4",
// U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE
- /* 63 */ "\u06F5",
+ /* 64 */ "\u06F5",
// U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX
- /* 64 */ "\u06F6",
+ /* 65 */ "\u06F6",
// U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN
- /* 65 */ "\u06F7",
+ /* 66 */ "\u06F7",
// U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT
- /* 66 */ "\u06F8",
+ /* 67 */ "\u06F8",
// U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE
- /* 67 */ "\u06F9",
+ /* 68 */ "\u06F9",
// U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO
- /* 68 */ "\u06F0",
+ /* 69 */ "\u06F0",
// Label for "switch to symbols" key.
// U+061F: "؟" ARABIC QUESTION MARK
- /* 69 */ "\u06F3\u06F2\u06F1\u061F",
+ /* 70 */ "\u06F3\u06F2\u06F1\u061F",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 70 */ "\u06F3\u06F2\u06F1",
- /* 71 */ "1",
- /* 72 */ "2",
- /* 73 */ "3",
- /* 74 */ "4",
- /* 75 */ "5",
- /* 76 */ "6",
- /* 77 */ "7",
- /* 78 */ "8",
- /* 79 */ "9",
+ /* 71 */ "\u06F3\u06F2\u06F1",
+ /* 72 */ "1",
+ /* 73 */ "2",
+ /* 74 */ "3",
+ /* 75 */ "4",
+ /* 76 */ "5",
+ /* 77 */ "6",
+ /* 78 */ "7",
+ /* 79 */ "8",
+ /* 80 */ "9",
// U+066B: "٫" ARABIC DECIMAL SEPARATOR
// U+066C: "٬" ARABIC THOUSANDS SEPARATOR
- /* 80 */ "0,\u066B,\u066C",
- /* 81~ */
+ /* 81 */ "0,\u066B,\u066C",
+ /* 82~ */
null, null, null, null, null, null, null, null, null, null,
- /* ~90 */
+ /* ~91 */
// U+060C: "،" ARABIC COMMA
- /* 91 */ "\u060C",
- /* 92 */ "\\,",
- /* 93 */ "\u061F",
- /* 94 */ "\u061B",
+ /* 92 */ "\u060C",
+ /* 93 */ "\\,",
+ /* 94 */ "\u061F",
+ /* 95 */ "\u061B",
// U+066A: "٪" ARABIC PERCENT SIGN
- /* 95 */ "\u066A",
- /* 96 */ null,
- /* 97 */ "?",
- /* 98 */ ";",
+ /* 96 */ "\u066A",
+ /* 97 */ null,
+ /* 98 */ "?",
+ /* 99 */ ";",
// U+2030: "‰" PER MILLE SIGN
- /* 99 */ "\\%,\u2030",
+ /* 100 */ "\\%,\u2030",
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
// U+061F: "؟" ARABIC QUESTION MARK
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- /* 100 */ "\u060C",
- /* 101 */ "!",
- /* 102 */ "!,\\,",
- /* 103 */ "\u061F",
- /* 104 */ "\u061F,?",
- /* 105 */ "\u060C",
- /* 106 */ "\u061F",
- /* 107 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\u00AB|\u00BB,\u00BB|\u00AB",
+ /* 101 */ "\u060C",
+ /* 102 */ "!",
+ /* 103 */ "!,\\,",
+ /* 104 */ "\u061F",
+ /* 105 */ "\u061F,?",
+ /* 106 */ "\u060C",
+ /* 107 */ "\u061F",
+ /* 108 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\u00AB|\u00BB,\u00BB|\u00AB",
};
/* Language fi: Finnish */
@@ -1512,48 +1554,48 @@ public final class KeyboardTextsSet {
// U+0917: "ग" DEVANAGARI LETTER GA
/* 42 */ "\u0915\u0916\u0917",
/* 43~ */
- null, null, null, null,
- /* ~46 */
+ null, null, null, null, null,
+ /* ~47 */
// U+20B9: "₹" INDIAN RUPEE SIGN
- /* 47 */ "\u20B9",
- /* 48~ */
+ /* 48 */ "\u20B9",
+ /* 49~ */
null, null, null, null, null, null, null, null, null, null, null,
- /* ~58 */
+ /* ~59 */
// U+0967: "१" DEVANAGARI DIGIT ONE
- /* 59 */ "\u0967",
+ /* 60 */ "\u0967",
// U+0968: "२" DEVANAGARI DIGIT TWO
- /* 60 */ "\u0968",
+ /* 61 */ "\u0968",
// U+0969: "३" DEVANAGARI DIGIT THREE
- /* 61 */ "\u0969",
+ /* 62 */ "\u0969",
// U+096A: "४" DEVANAGARI DIGIT FOUR
- /* 62 */ "\u096A",
+ /* 63 */ "\u096A",
// U+096B: "५" DEVANAGARI DIGIT FIVE
- /* 63 */ "\u096B",
+ /* 64 */ "\u096B",
// U+096C: "६" DEVANAGARI DIGIT SIX
- /* 64 */ "\u096C",
+ /* 65 */ "\u096C",
// U+096D: "७" DEVANAGARI DIGIT SEVEN
- /* 65 */ "\u096D",
+ /* 66 */ "\u096D",
// U+096E: "८" DEVANAGARI DIGIT EIGHT
- /* 66 */ "\u096E",
+ /* 67 */ "\u096E",
// U+096F: "९" DEVANAGARI DIGIT NINE
- /* 67 */ "\u096F",
+ /* 68 */ "\u096F",
// U+0966: "०" DEVANAGARI DIGIT ZERO
- /* 68 */ "\u0966",
+ /* 69 */ "\u0966",
// Label for "switch to symbols" key.
- /* 69 */ "?\u0967\u0968\u0969",
+ /* 70 */ "?\u0967\u0968\u0969",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 70 */ "\u0967\u0968\u0969",
- /* 71 */ "1",
- /* 72 */ "2",
- /* 73 */ "3",
- /* 74 */ "4",
- /* 75 */ "5",
- /* 76 */ "6",
- /* 77 */ "7",
- /* 78 */ "8",
- /* 79 */ "9",
- /* 80 */ "0",
+ /* 71 */ "\u0967\u0968\u0969",
+ /* 72 */ "1",
+ /* 73 */ "2",
+ /* 74 */ "3",
+ /* 75 */ "4",
+ /* 76 */ "5",
+ /* 77 */ "6",
+ /* 78 */ "7",
+ /* 79 */ "8",
+ /* 80 */ "9",
+ /* 81 */ "0",
};
/* Language hr: Croatian */
@@ -1581,6 +1623,14 @@ public final class KeyboardTextsSet {
// 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, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_rqm",
+ /* 44 */ "!text/double_9qm_rqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language hu: Hungarian */
@@ -1626,6 +1676,15 @@ public final class KeyboardTextsSet {
// U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
// U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
/* 4 */ "\u00FA,\u00FC,\u0171,\u00FB,\u00F9,\u016B",
+ /* 5~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_rqm",
+ /* 44 */ "!text/double_9qm_rqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language is: Icelandic */
@@ -1689,6 +1748,12 @@ public final class KeyboardTextsSet {
/* 21 */ "\u00E6",
// U+00FE: "þ" LATIN SMALL LETTER THORN
/* 22 */ "\u00FE",
+ /* 23~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language it: Italian */
@@ -1748,45 +1813,38 @@ public final class KeyboardTextsSet {
// U+05D1: "ב" HEBREW LETTER BET
// U+05D2: "ג" HEBREW LETTER GIMEL
/* 42 */ "\u05D0\u05D1\u05D2",
- /* 43 */ null,
- // TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK
- // <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
- /* 44 */ "!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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- /* 45 */ "!fixedColumnOrder!4,\u201C,\u201D,\u00AB|\u00BB,\u00BB|\u00AB,\u2018,\u2019,\u201A,\u201B",
- /* 46 */ null,
- // U+20AA: "₪" NEW SHEQEL SIGN
- /* 47 */ "\u20AA",
- /* 48 */ null,
- /* 49 */ null,
+ // 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+201C: "“" LEFT DOUBLE QUOTATION MARK
+ // U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ // U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
+ /* 43 */ "\u2018,\u2019,\u201A",
+ /* 44 */ "\u201C,\u201D,\u201E",
+ /* 45 */ "!text/single_laqm_raqm_rtl",
+ /* 46 */ "!text/double_laqm_raqm_rtl",
+ /* 47~ */
+ null, null, null, null,
+ /* ~50 */
// U+2605: "★" BLACK STAR
- /* 50 */ "\u2605",
- /* 51 */ null,
+ /* 51 */ "\u2605",
+ /* 52 */ null,
// U+00B1: "±" PLUS-MINUS SIGN
// U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
- /* 52 */ "\u00B1,\uFB29",
+ /* 53 */ "\u00B1,\uFB29",
// The all letters need to be mirrored are found at
// http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
- /* 53 */ "!fixedColumnOrder!3,<|>,{|},[|]",
- /* 54 */ "!fixedColumnOrder!3,>|<,}|{,]|[",
+ /* 54 */ "!fixedColumnOrder!3,<|>,{|},[|]",
+ /* 55 */ "!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
- /* 55 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
- /* 56 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 56 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 57 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
};
/* Language ka: Georgian */
@@ -1801,6 +1859,8 @@ public final class KeyboardTextsSet {
// U+10D1: "ბ" GEORGIAN LETTER BAN
// U+10D2: "გ" GEORGIAN LETTER GAN
/* 42 */ "\u10D0\u10D1\u10D2",
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language ky: Kirghiz */
@@ -1930,6 +1990,12 @@ public final class KeyboardTextsSet {
// U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
// U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
/* 15 */ "\u0123,\u011F",
+ /* 16~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language lv: Latvian */
@@ -2019,6 +2085,12 @@ public final class KeyboardTextsSet {
// U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
// U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
/* 15 */ "\u0123,\u011F",
+ /* 16~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language mk: Macedonian */
@@ -2045,21 +2117,8 @@ public final class KeyboardTextsSet {
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
/* 42 */ "\u0410\u0411\u0412",
- /* 43 */ 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,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
- /* 44 */ "!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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- /* 45 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language mn: Mongolian */
@@ -2075,10 +2134,10 @@ public final class KeyboardTextsSet {
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
/* 42 */ "\u0410\u0411\u0412",
/* 43~ */
- null, null, null, null,
- /* ~46 */
+ null, null, null, null, null,
+ /* ~47 */
// U+20AE: "₮" TUGRIK SIGN
- /* 47 */ "\u20AE",
+ /* 48 */ "\u20AE",
};
/* Language nb: Norwegian Bokmål */
@@ -2126,6 +2185,12 @@ public final class KeyboardTextsSet {
/* 23 */ "\u00F6",
// U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
/* 24 */ "\u00E4",
+ /* 25~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_rqm",
+ /* 44 */ "!text/double_9qm_rqm",
};
/* Language nl: Dutch */
@@ -2177,6 +2242,13 @@ public final class KeyboardTextsSet {
/* 7 */ null,
// U+0133: "ij" LATIN SMALL LIGATURE IJ
/* 8 */ "\u0133",
+ /* 9~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_rqm",
+ /* 44 */ "!text/double_9qm_rqm",
};
/* Language pl: Polish */
@@ -2231,6 +2303,12 @@ public final class KeyboardTextsSet {
/* 13 */ null,
// U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
/* 14 */ "\u0142",
+ /* 15~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_rqm",
+ /* 44 */ "!text/double_9qm_rqm",
};
/* Language pt: Portuguese */
@@ -2330,6 +2408,13 @@ public final class KeyboardTextsSet {
/* ~10 */
// U+021B: "ț" LATIN SMALL LETTER T WITH COMMA BELOW
/* 11 */ "\u021B",
+ /* 12~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_rqm",
+ /* 44 */ "!text/double_9qm_rqm",
};
/* Language ru: Russian */
@@ -2364,6 +2449,8 @@ public final class KeyboardTextsSet {
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
/* 42 */ "\u0410\u0411\u0412",
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
};
/* Language sk: Slovak */
@@ -2454,6 +2541,14 @@ public final class KeyboardTextsSet {
// U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
// U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
/* 15 */ "\u0123,\u011F",
+ /* 16~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language sl: Slovenian */
@@ -2474,6 +2569,14 @@ public final class KeyboardTextsSet {
/* 11 */ null,
// U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
/* 12 */ "\u017E",
+ /* 13~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~42 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language sr: Serbian */
@@ -2519,21 +2622,10 @@ public final class KeyboardTextsSet {
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
/* 42 */ "\u0410\u0411\u0412",
- /* 43 */ 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,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string>
- /* 44 */ "!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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- /* 45 */ "!fixedColumnOrder!5,\u201E,\u201C,\u201D,\u00AB,\u00BB,\u2018,\u2019,\u201A,\u201B",
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language sv: Swedish */
@@ -2576,6 +2668,12 @@ public final class KeyboardTextsSet {
/* 23 */ "\u00F8",
// U+00E6: "æ" LATIN SMALL LETTER AE
/* 24 */ "\u00E6",
+ /* 25~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null,
+ /* ~44 */
+ /* 45 */ "!text/single_raqm_laqm",
+ /* 46 */ "!text/double_raqm_laqm",
};
/* Language sw: Swahili */
@@ -2642,10 +2740,10 @@ public final class KeyboardTextsSet {
// U+0E04: "ค" THAI CHARACTER KHO KHWAI
/* 42 */ "\u0E01\u0E02\u0E04",
/* 43~ */
- null, null, null, null,
- /* ~46 */
+ null, null, null, null, null,
+ /* ~47 */
// U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT
- /* 47 */ "\u0E3F",
+ /* 48 */ "\u0E3F",
};
/* Language tl: Tagalog */
@@ -2780,11 +2878,13 @@ public final class KeyboardTextsSet {
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
/* 42 */ "\u0410\u0411\u0412",
- /* 43~ */
- null, null, null, null,
- /* ~46 */
+ /* 43 */ "!text/single_9qm_lqm",
+ /* 44 */ "!text/double_9qm_lqm",
+ /* 45~ */
+ null, null, null,
+ /* ~47 */
// U+20B4: "₴" HRYVNIA SIGN
- /* 47 */ "\u20B4",
+ /* 48 */ "\u20B4",
};
/* Language vi: Vietnamese */
@@ -2869,10 +2969,10 @@ public final class KeyboardTextsSet {
/* 10~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null,
- /* ~46 */
+ null, null, null, null, null, null, null, null,
+ /* ~47 */
// U+20AB: "₫" DONG SIGN
- /* 47 */ "\u20AB",
+ /* 48 */ "\u20AB",
};
/* Language zu: Zulu */
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index ad3163347..ab2a12fd0 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -16,7 +16,6 @@
package com.android.inputmethod.latin;
-import android.content.Context;
import android.text.TextUtils;
import android.util.SparseArray;
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index d9d664fb5..0d0ce5756 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -74,6 +74,8 @@ public final class BinaryDictionaryFileDumper {
// The path fragment to append after the client ID for dictionary info requests.
private static final String QUERY_PATH_DICT_INFO = "dict";
+ // The path fragment to append after the client ID for dictionary datafile requests.
+ private static final String QUERY_PATH_DATAFILE = "datafile";
// The path fragment to append after the client ID for updating the metadata URI.
private static final String QUERY_PATH_METADATA = "metadata";
private static final String INSERT_METADATA_CLIENT_ID_COLUMN = "clientid";
@@ -156,7 +158,7 @@ public final class BinaryDictionaryFileDumper {
c.close();
return Collections.<WordListInfo>emptyList();
}
- final List<WordListInfo> list = CollectionUtils.newArrayList();
+ final ArrayList<WordListInfo> list = CollectionUtils.newArrayList();
do {
final String wordListId = c.getString(0);
final String wordListLocale = c.getString(1);
@@ -186,13 +188,18 @@ public final class BinaryDictionaryFileDumper {
/**
* Helper method to encapsulate exception handling.
*/
- private static AssetFileDescriptor openAssetFileDescriptor(final ContentResolver resolver,
- final Uri uri) {
+ private static AssetFileDescriptor openAssetFileDescriptor(
+ final ContentProviderClient providerClient, final Uri uri) {
try {
- return resolver.openAssetFileDescriptor(uri, "r");
+ return providerClient.openAssetFile(uri, "r");
} catch (FileNotFoundException e) {
- // I don't want to log the word list URI here for security concerns
- Log.e(TAG, "Could not find a word list from the dictionary provider.");
+ // I don't want to log the word list URI here for security concerns. The exception
+ // contains the name of the file, so let's not pass it to Log.e here.
+ Log.e(TAG, "Could not find a word list from the dictionary provider."
+ /* intentionally don't pass the exception (see comment above) */);
+ return null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't communicate with the dictionary pack", e);
return null;
}
}
@@ -202,9 +209,8 @@ public final class BinaryDictionaryFileDumper {
* to the cache file name designated by its id and locale, overwriting it if already present
* and creating it (and its containing directory) if necessary.
*/
- private static AssetFileAddress cacheWordList(final String id, final String locale,
- final ContentResolver resolver, final Context context) {
-
+ private static AssetFileAddress cacheWordList(final String wordlistId, final String locale,
+ final ContentProviderClient providerClient, final Context context) {
final int COMPRESSED_CRYPTED_COMPRESSED = 0;
final int CRYPTED_COMPRESSED = 1;
final int COMPRESSED_CRYPTED = 2;
@@ -214,11 +220,20 @@ public final class BinaryDictionaryFileDumper {
final int MODE_MIN = COMPRESSED_CRYPTED_COMPRESSED;
final int MODE_MAX = NONE;
- final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id);
- final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context);
+ final String clientId = context.getString(R.string.dictionary_pack_client_id);
+ final Uri.Builder wordListUriBuilder;
+ try {
+ wordListUriBuilder = getContentUriBuilderForType(clientId,
+ providerClient, QUERY_PATH_DATAFILE, wordlistId /* extraPath */);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't communicate with the dictionary pack", e);
+ return null;
+ }
+ final String finalFileName =
+ DictionaryInfoUtils.getCacheFileName(wordlistId, locale, context);
String tempFileName;
try {
- tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
+ tempFileName = BinaryDictionaryGetter.getTempFileName(wordlistId, context);
} catch (IOException e) {
Log.e(TAG, "Can't open the temporary file", e);
return null;
@@ -236,7 +251,7 @@ public final class BinaryDictionaryFileDumper {
final Uri wordListUri = wordListUriBuilder.build();
try {
// Open input.
- afd = openAssetFileDescriptor(resolver, wordListUri);
+ afd = openAssetFileDescriptor(providerClient, wordListUri);
// If we can't open it at all, don't even try a number of times.
if (null == afd) return null;
originalSourceStream = afd.createInputStream();
@@ -284,10 +299,10 @@ public final class BinaryDictionaryFileDumper {
}
wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
QUERY_PARAMETER_SUCCESS);
- if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) {
+ if (0 >= providerClient.delete(wordListUriBuilder.build(), null, null)) {
Log.e(TAG, "Could not have the dictionary pack delete a word list");
}
- BinaryDictionaryGetter.removeFilesWithIdExcept(context, id, finalFile);
+ BinaryDictionaryGetter.removeFilesWithIdExcept(context, wordlistId, finalFile);
// Success! Close files (through the finally{} clause) and return.
return AssetFileAddress.makeFromFileName(finalFileName);
} catch (Exception e) {
@@ -327,8 +342,12 @@ public final class BinaryDictionaryFileDumper {
// as invalid.
wordListUriBuilder.appendQueryParameter(QUERY_PARAMETER_DELETE_RESULT,
QUERY_PARAMETER_FAILURE);
- if (0 >= resolver.delete(wordListUriBuilder.build(), null, null)) {
- Log.e(TAG, "In addition, we were unable to delete it.");
+ try {
+ if (0 >= providerClient.delete(wordListUriBuilder.build(), null, null)) {
+ Log.e(TAG, "In addition, we were unable to delete it.");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "In addition, communication with the dictionary provider was cut", e);
}
return null;
}
@@ -345,17 +364,27 @@ public final class BinaryDictionaryFileDumper {
*/
public static List<AssetFileAddress> cacheWordListsFromContentProvider(final Locale locale,
final Context context, final boolean hasDefaultWordList) {
- final ContentResolver resolver = context.getContentResolver();
- final List<WordListInfo> idList = getWordListWordListInfos(locale, context,
- hasDefaultWordList);
- final List<AssetFileAddress> fileAddressList = CollectionUtils.newArrayList();
- for (WordListInfo id : idList) {
- final AssetFileAddress afd = cacheWordList(id.mId, id.mLocale, resolver, context);
- if (null != afd) {
- fileAddressList.add(afd);
+ final ContentProviderClient providerClient = context.getContentResolver().
+ acquireContentProviderClient(getProviderUriBuilder("").build());
+ if (null == providerClient) {
+ Log.e(TAG, "Can't establish communication with the dictionary provider");
+ return CollectionUtils.newArrayList();
+ }
+ try {
+ final List<WordListInfo> idList = getWordListWordListInfos(locale, context,
+ hasDefaultWordList);
+ final ArrayList<AssetFileAddress> fileAddressList = CollectionUtils.newArrayList();
+ for (WordListInfo id : idList) {
+ final AssetFileAddress afd =
+ cacheWordList(id.mId, id.mLocale, providerClient, context);
+ if (null != afd) {
+ fileAddressList.add(afd);
+ }
}
+ return fileAddressList;
+ } finally {
+ providerClient.release();
}
- return fileAddressList;
}
/**
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index a96738b3e..e913f2852 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -68,9 +68,13 @@ final class BinaryDictionaryGetter {
/**
* Generates a unique temporary file name in the app cache directory.
*/
- public static String getTempFileName(String id, Context context) throws IOException {
- return File.createTempFile(DictionaryInfoUtils.replaceFileNameDangerousCharacters(id),
- null).getAbsolutePath();
+ public static String getTempFileName(final String id, final Context context)
+ throws IOException {
+ final String safeId = DictionaryInfoUtils.replaceFileNameDangerousCharacters(id);
+ // If the first argument is less than three chars, createTempFile throws a
+ // RuntimeException. We don't really care about what name we get, so just
+ // put a three-chars prefix makes us safe.
+ return File.createTempFile("xxx" + safeId, null).getAbsolutePath();
}
/**
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 422448edf..50e50233e 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -179,14 +179,13 @@ public final class Constants {
public static final int CODE_DELETE = -4;
public static final int CODE_SETTINGS = -5;
public static final int CODE_SHORTCUT = -6;
- public static final int CODE_ACTION_ENTER = -7;
- public static final int CODE_ACTION_NEXT = -8;
- public static final int CODE_ACTION_PREVIOUS = -9;
- public static final int CODE_LANGUAGE_SWITCH = -10;
- public static final int CODE_RESEARCH = -11;
- public static final int CODE_SHIFT_ENTER = -12;
+ public static final int CODE_ACTION_NEXT = -7;
+ public static final int CODE_ACTION_PREVIOUS = -8;
+ public static final int CODE_LANGUAGE_SWITCH = -9;
+ public static final int CODE_RESEARCH = -10;
+ public static final int CODE_SHIFT_ENTER = -11;
// Code value representing the code is not specified.
- public static final int CODE_UNSPECIFIED = -13;
+ public static final int CODE_UNSPECIFIED = -12;
public static boolean isLetterCode(final int code) {
return code >= CODE_SPACE;
@@ -200,7 +199,6 @@ public final class Constants {
case CODE_DELETE: return "delete";
case CODE_SETTINGS: return "settings";
case CODE_SHORTCUT: return "shortcut";
- case CODE_ACTION_ENTER: return "actionEnter";
case CODE_ACTION_NEXT: return "actionNext";
case CODE_ACTION_PREVIOUS: return "actionPrevious";
case CODE_LANGUAGE_SWITCH: return "languageSwitch";
diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java
index 7df266ef2..c2aade64d 100644
--- a/java/src/com/android/inputmethod/latin/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/DebugSettings.java
@@ -57,7 +57,7 @@ public final class DebugSettings extends PreferenceFragment
if (usabilityStudyPref instanceof CheckBoxPreference) {
final CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref;
checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE,
- ResearchLogger.DEFAULT_USABILITY_STUDY_MODE));
+ LatinImeLogger.getUsabilityStudyMode(prefs)));
checkbox.setSummary(R.string.settings_warning_researcher_mode);
}
final Preference statisticsLoggingPref = findPreference(PREF_STATISTICS_LOGGING);
diff --git a/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java
index d2a946bf5..dcfa483f8 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java
@@ -41,8 +41,6 @@ public class DictionaryInfoUtils {
private static final String RESOURCE_PACKAGE_NAME =
DictionaryInfoUtils.class.getPackage().getName();
private static final String DEFAULT_MAIN_DICT = "main";
- private static final String ID_CATEGORY_SEPARATOR =
- BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR;
private static final String MAIN_DICT_PREFIX = "main_";
// 6 digits - unicode is limited to 21 bits
private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6;
@@ -51,24 +49,28 @@ public class DictionaryInfoUtils {
private static final String LOCALE_COLUMN = "locale";
private static final String WORDLISTID_COLUMN = "id";
private static final String LOCAL_FILENAME_COLUMN = "filename";
+ private static final String DESCRIPTION_COLUMN = "description";
private static final String DATE_COLUMN = "date";
private static final String FILESIZE_COLUMN = "filesize";
private static final String VERSION_COLUMN = "version";
+ public final String mId;
public final Locale mLocale;
+ public final String mDescription;
public final AssetFileAddress mFileAddress;
public final int mVersion;
- public final String mId;
- public DictionaryInfo(final Locale locale, final AssetFileAddress fileAddress,
- final int version) {
+ public DictionaryInfo(final String id, final Locale locale, final String description,
+ final AssetFileAddress fileAddress, final int version) {
+ mId = id;
mLocale = locale;
+ mDescription = description;
mFileAddress = fileAddress;
mVersion = version;
- mId = DEFAULT_MAIN_DICT + ID_CATEGORY_SEPARATOR + mLocale;
}
public ContentValues toContentValues() {
final ContentValues values = new ContentValues();
values.put(WORDLISTID_COLUMN, mId);
values.put(LOCALE_COLUMN, mLocale.toString());
+ values.put(DESCRIPTION_COLUMN, mDescription);
values.put(LOCAL_FILENAME_COLUMN, mFileAddress.mFilename);
values.put(DATE_COLUMN,
new File(mFileAddress.mFilename).lastModified() / DateUtils.SECOND_IN_MILLIS);
@@ -283,9 +285,11 @@ public class DictionaryInfoUtils {
final AssetFileAddress fileAddress) {
final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeaderOrNull(
new File(fileAddress.mFilename), fileAddress.mOffset, fileAddress.mLength);
+ final String id = header.getId();
final Locale locale = LocaleUtils.constructLocaleFromString(header.getLocaleString());
+ final String description = header.getDescription();
final String version = header.getVersion();
- return new DictionaryInfo(locale, fileAddress, Integer.parseInt(version));
+ return new DictionaryInfo(id, locale, description, fileAddress, Integer.parseInt(version));
}
private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList,
diff --git a/java/src/com/android/inputmethod/latin/InputTypeUtils.java b/java/src/com/android/inputmethod/latin/InputTypeUtils.java
index 2ad619b82..ecb20144b 100644
--- a/java/src/com/android/inputmethod/latin/InputTypeUtils.java
+++ b/java/src/com/android/inputmethod/latin/InputTypeUtils.java
@@ -106,18 +106,13 @@ public final class InputTypeUtils implements InputType {
}
public static int getImeOptionsActionIdFromEditorInfo(final EditorInfo editorInfo) {
- final int actionId = editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
if ((editorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
return EditorInfo.IME_ACTION_NONE;
} else if (editorInfo.actionLabel != null) {
return IME_ACTION_CUSTOM_LABEL;
} else {
- return actionId;
+ // Note: this is different from editorInfo.actionId, hence "ImeOptionsActionId"
+ return editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
}
}
-
- public static int getConcreteActionIdFromEditorInfo(final EditorInfo editorInfo) {
- final int actionId = getImeOptionsActionIdFromEditorInfo(editorInfo);
- return actionId == InputTypeUtils.IME_ACTION_CUSTOM_LABEL ? editorInfo.actionId : actionId;
- }
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 73ace2bfa..252fb02c8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -132,6 +132,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private View mKeyPreviewBackingView;
private View mSuggestionsContainer;
private SuggestionStripView mSuggestionStripView;
+ // Never null
+ private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
@UsedForTesting Suggest mSuggest;
private CompletionInfo[] mApplicationSpecifiedCompletions;
private ApplicationInfo mTargetApplicationInfo;
@@ -165,7 +167,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
private boolean mExpectingUpdateSelection;
private int mDeleteCount;
private long mLastKeyTime;
- private int mActionId;
private TreeSet<Long> mCurrentlyPressedHardwareKeys = CollectionUtils.newTreeSet();
// Member variables for remembering the current device orientation.
@@ -427,7 +428,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
initSuggest();
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.getInstance().init(this, mKeyboardSwitcher);
+ ResearchLogger.getInstance().init(this, mKeyboardSwitcher, mSuggest);
}
mDisplayOrientation = getResources().getConfiguration().orientation;
@@ -562,6 +563,9 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
mSettings.onDestroy();
unregisterReceiver(mReceiver);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().onDestroy();
+ }
// TODO: The experimental version is not supported by the Dictionary Pack Service yet.
if (!ProductionFlag.IS_EXPERIMENTAL) {
unregisterReceiver(mDictionaryPackInstallReceiver);
@@ -729,6 +733,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// otherwise it will clear the suggestion strip.
setPunctuationSuggestions();
}
+ mSuggestedWords = SuggestedWords.EMPTY;
mConnection.resetCachesUponCursorMove(editorInfo.initialSelStart);
@@ -756,7 +761,6 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
mLastSelectionStart = editorInfo.initialSelStart;
mLastSelectionEnd = editorInfo.initialSelEnd;
- mActionId = InputTypeUtils.getConcreteActionIdFromEditorInfo(editorInfo);
mHandler.cancelUpdateSuggestionStrip();
mHandler.cancelDoubleSpacePeriodTimer();
@@ -954,6 +958,10 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
LatinImeLogger.commit();
mKeyboardSwitcher.onHideWindow();
+ if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
+ AccessibleKeyboardViewProxy.getInstance().onHideWindow();
+ }
+
if (TRACE) Debug.stopMethodTracing();
if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
mOptionsDialog.dismiss();
@@ -994,7 +1002,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
false /* isPrediction */);
// When in fullscreen mode, show completions generated by the application
final boolean isAutoCorrection = false;
- setSuggestionStrip(suggestedWords, isAutoCorrection);
+ setSuggestedWords(suggestedWords, isAutoCorrection);
setAutoCorrectionIndicator(isAutoCorrection);
setSuggestionStripShown(true);
if (ProductionFlag.IS_EXPERIMENTAL) {
@@ -1119,7 +1127,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (mSettings.getCurrent().mBigramPredictionEnabled) {
clearSuggestionStrip();
} else {
- setSuggestionStrip(mSettings.getCurrent().mSuggestPuncList, false);
+ setSuggestedWords(mSettings.getCurrent().mSuggestPuncList, false);
}
mConnection.resetCachesUponCursorMove(newCursorPosition);
}
@@ -1393,13 +1401,28 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
ResearchLogger.getInstance().onResearchKeySelected(this);
}
break;
- case Constants.CODE_ACTION_ENTER:
- if (EditorInfo.IME_ACTION_NONE != mActionId
- && EditorInfo.IME_ACTION_UNSPECIFIED != mActionId) {
- performEditorAction(mActionId);
- break;
+ case Constants.CODE_ENTER:
+ final EditorInfo editorInfo = getCurrentInputEditorInfo();
+ final int imeOptionsActionId =
+ InputTypeUtils.getImeOptionsActionIdFromEditorInfo(editorInfo);
+ if (InputTypeUtils.IME_ACTION_CUSTOM_LABEL == imeOptionsActionId) {
+ // Either we have an actionLabel and we should performEditorAction with actionId
+ // regardless of its value.
+ performEditorAction(editorInfo.actionId);
+ } else if (EditorInfo.IME_ACTION_NONE != imeOptionsActionId) {
+ // We didn't have an actionLabel, but we had another action to execute.
+ // EditorInfo.IME_ACTION_NONE explicitly means no action. In contrast,
+ // EditorInfo.IME_ACTION_UNSPECIFIED is the default value for an action, so it
+ // means there should be an action and the app didn't bother to set a specific
+ // code for it - presumably it only handles one. It does not have to be treated
+ // in any specific way: anything that is not IME_ACTION_NONE should be sent to
+ // performEditorAction.
+ performEditorAction(imeOptionsActionId);
+ } else {
+ // No action label, and the action from imeOptions is NONE: this is a regular
+ // enter key that should input a carriage return.
+ didAutoCorrect = handleNonSpecialCharacter(Constants.CODE_ENTER, x, y, spaceState);
}
- didAutoCorrect = handleNonSpecialCharacter(Constants.CODE_ENTER, x, y, spaceState);
break;
case Constants.CODE_SHIFT_ENTER:
didAutoCorrect = handleNonSpecialCharacter(Constants.CODE_ENTER, x, y, spaceState);
@@ -1967,8 +1990,8 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// Outside LatinIME, only used by the test suite.
@UsedForTesting
boolean isShowingPunctuationList() {
- if (mSuggestionStripView == null) return false;
- return mSettings.getCurrent().mSuggestPuncList == mSuggestionStripView.getSuggestions();
+ if (mSuggestedWords == null) return false;
+ return mSettings.getCurrent().mSuggestPuncList == mSuggestedWords;
}
private boolean isSuggestionsStripVisible() {
@@ -1984,11 +2007,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
private void clearSuggestionStrip() {
- setSuggestionStrip(SuggestedWords.EMPTY, false);
+ setSuggestedWords(SuggestedWords.EMPTY, false);
setAutoCorrectionIndicator(false);
}
- private void setSuggestionStrip(final SuggestedWords words, final boolean isAutoCorrection) {
+ private void setSuggestedWords(final SuggestedWords words, final boolean isAutoCorrection) {
+ mSuggestedWords = words;
if (mSuggestionStripView != null) {
mSuggestionStripView.setSuggestions(words);
mKeyboardSwitcher.onAutoCorrectionStateChanged(isAutoCorrection);
@@ -2071,15 +2095,16 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
private SuggestedWords getOlderSuggestions(final String typedWord) {
- SuggestedWords previousSuggestions = mSuggestionStripView.getSuggestions();
- if (previousSuggestions == mSettings.getCurrent().mSuggestPuncList) {
- previousSuggestions = SuggestedWords.EMPTY;
+ SuggestedWords previousSuggestedWords = mSuggestedWords;
+ if (previousSuggestedWords == mSettings.getCurrent().mSuggestPuncList) {
+ previousSuggestedWords = SuggestedWords.EMPTY;
}
if (typedWord == null) {
- return previousSuggestions;
+ return previousSuggestedWords;
}
final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
- SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord, previousSuggestions);
+ SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord,
+ previousSuggestedWords);
return new SuggestedWords(typedWordAndPreviousSuggestions,
false /* typedWordValid */,
false /* hasAutoCorrectionCandidate */,
@@ -2101,7 +2126,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
}
mWordComposer.setAutoCorrection(autoCorrection);
final boolean isAutoCorrection = suggestedWords.willAutoCorrect();
- setSuggestionStrip(suggestedWords, isAutoCorrection);
+ setSuggestedWords(suggestedWords, isAutoCorrection);
setAutoCorrectionIndicator(isAutoCorrection);
setSuggestionStripShown(isSuggestionsStripVisible());
}
@@ -2124,7 +2149,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
Stats.onAutoCorrection(typedWord, autoCorrection, separatorString, mWordComposer);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
- final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions();
+ final SuggestedWords suggestedWords = mSuggestedWords;
ResearchLogger.latinIme_commitCurrentAutoCorrection(typedWord, autoCorrection,
separatorString, mWordComposer.isBatchMode(), suggestedWords);
}
@@ -2149,7 +2174,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
// interface
@Override
public void pickSuggestionManually(final int index, final String suggestion) {
- final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions();
+ final SuggestedWords suggestedWords = mSuggestedWords;
// If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
if (suggestion.length() == 1 && isShowingPunctuationList()) {
// Word separators are suggested before the user inputs something.
@@ -2181,6 +2206,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (mSettings.getCurrent().isApplicationSpecifiedCompletionsOn()
&& mApplicationSpecifiedCompletions != null
&& index >= 0 && index < mApplicationSpecifiedCompletions.length) {
+ mSuggestedWords = SuggestedWords.EMPTY;
if (mSuggestionStripView != null) {
mSuggestionStripView.clear();
}
@@ -2236,7 +2262,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
*/
private void commitChosenWord(final String chosenWord, final int commitType,
final String separatorString) {
- final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions();
+ final SuggestedWords suggestedWords = mSuggestedWords;
mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
this, chosenWord, suggestedWords, mIsMainDictionaryAvailable), 1);
// Add the word to the user history dictionary
@@ -2253,7 +2279,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
if (mSettings.getCurrent().mBigramPredictionEnabled) {
clearSuggestionStrip();
} else {
- setSuggestionStrip(mSettings.getCurrent().mSuggestPuncList, false);
+ setSuggestedWords(mSettings.getCurrent().mSuggestPuncList, false);
}
setAutoCorrectionIndicator(false);
setSuggestionStripShown(isSuggestionsStripVisible());
@@ -2550,6 +2576,12 @@ public final class LatinIME extends InputMethodService implements KeyboardAction
dialog.show();
}
+ // TODO: can this be removed somehow without breaking the tests?
+ @UsedForTesting
+ /* package for test */ String getFirstSuggestedWord() {
+ return mSuggestedWords.size() > 0 ? mSuggestedWords.getWord(0) : null;
+ }
+
public void debugDumpStateAndCrashWithException(final String context) {
final StringBuilder s = new StringBuilder();
s.append("Target application : ").append(mTargetApplicationInfo.name)
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index e4e8b94b2..3f2b0a3f4 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -37,6 +37,10 @@ public final class LatinImeLogger implements SharedPreferences.OnSharedPreferenc
public static void commit() {
}
+ public static boolean getUsabilityStudyMode(final SharedPreferences prefs) {
+ return false;
+ }
+
public static void onDestroy() {
}
diff --git a/java/src/com/android/inputmethod/latin/LocaleUtils.java b/java/src/com/android/inputmethod/latin/LocaleUtils.java
index fcf727041..5fde8158a 100644
--- a/java/src/com/android/inputmethod/latin/LocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/LocaleUtils.java
@@ -180,14 +180,15 @@ public final class LocaleUtils {
synchronized (sLockForRunInLocale) {
final Configuration conf = res.getConfiguration();
final Locale oldLocale = conf.locale;
+ final boolean needsChange = (newLocale != null && !newLocale.equals(oldLocale));
try {
- if (newLocale != null && !newLocale.equals(oldLocale)) {
+ if (needsChange) {
conf.locale = newLocale;
res.updateConfiguration(conf, null);
}
return job(res);
} finally {
- if (newLocale != null && !newLocale.equals(oldLocale)) {
+ if (needsChange) {
conf.locale = oldLocale;
res.updateConfiguration(conf, null);
}
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 02b44c7f6..435074bdb 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.preference.PreferenceManager;
@@ -64,6 +65,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_GESTURE_PREVIEW_TRAIL = "pref_gesture_preview_trail";
public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT =
"pref_gesture_floating_preview_text";
+ public static final String PREF_SHOW_SETUP_WIZARD_ICON = "pref_show_setup_wizard_icon";
public static final String PREF_INPUT_LANGUAGE = "input_language";
public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
@@ -260,4 +262,16 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static boolean readUseFullscreenMode(final Resources res) {
return res.getBoolean(R.bool.config_use_fullscreen_mode);
}
+
+ public static boolean readShowSetupWizardIcon(final SharedPreferences prefs,
+ final Context context) {
+ if (!prefs.contains(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
+ final ApplicationInfo appInfo = context.getApplicationInfo();
+ final boolean isApplicationInSystemImage =
+ (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ // Default value
+ return !isApplicationInSystemImage;
+ }
+ return prefs.getBoolean(Settings.PREF_SHOW_SETUP_WIZARD_ICON, false);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/SettingsFragment.java b/java/src/com/android/inputmethod/latin/SettingsFragment.java
index edd064c0b..4c90e485a 100644
--- a/java/src/com/android/inputmethod/latin/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/SettingsFragment.java
@@ -31,6 +31,7 @@ import android.preference.PreferenceScreen;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.latin.define.ProductionFlag;
+import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
import com.android.inputmethodcommon.InputMethodSettingsFragment;
public final class SettingsFragment extends InputMethodSettingsFragment
@@ -155,6 +156,10 @@ public final class SettingsFragment extends InputMethodSettingsFragment
removePreference(Settings.PREF_GESTURE_SETTINGS, getPreferenceScreen());
}
+ final CheckBoxPreference showSetupWizardIcon =
+ (CheckBoxPreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
+ showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, context));
+
setupKeyLongpressTimeoutSettings(prefs, res);
setupKeypressVibrationDurationSettings(prefs, res);
setupKeypressSoundVolumeSettings(prefs, res);
@@ -196,6 +201,8 @@ public final class SettingsFragment extends InputMethodSettingsFragment
final boolean gestureInputEnabled = Settings.readGestureInputEnabled(prefs, res);
setPreferenceEnabled(Settings.PREF_GESTURE_PREVIEW_TRAIL, gestureInputEnabled);
setPreferenceEnabled(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, gestureInputEnabled);
+ } else if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
+ LauncherIconVisibilityManager.updateSetupWizardIconVisibility(getActivity());
}
ensureConsistencyOfAutoCorrectionSettings();
updateVoiceModeSummary();
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
index 81bc9f5d7..528028328 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -263,9 +263,10 @@ public final class UserHistoryDictionary extends ExpandableDictionary {
UserHistoryDictIOUtils.readDictionaryBinary(
new UserHistoryDictIOUtils.ByteArrayWrapper(buffer), listener);
} catch (FileNotFoundException e) {
- Log.e(TAG, "when loading: file not found" + e);
+ // This is an expected condition: we don't have a user history dictionary for this
+ // language yet. It will be created sometime later.
} catch (IOException e) {
- Log.e(TAG, "IOException when open bytebuffer: " + e);
+ Log.e(TAG, "IOException on opening a bytebuffer", e);
} finally {
if (inStream != null) {
try {
@@ -328,7 +329,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary {
Thread.sleep(15000);
Log.w(TAG, "End stress in closing");
} catch (InterruptedException e) {
- Log.e(TAG, "In stress test: " + e);
+ Log.e(TAG, "In stress test", e);
}
}
@@ -343,7 +344,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary {
out.flush();
out.close();
} catch (IOException e) {
- Log.e(TAG, "IO Exception while writing file: " + e);
+ Log.e(TAG, "IO Exception while writing file", e);
} finally {
if (out != null) {
try {
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index acfcd5354..7a604dc6a 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -28,6 +28,7 @@ import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.io.BufferedReader;
@@ -77,6 +78,7 @@ public final class Utils {
private RingCharBuffer() {
// Intentional empty constructor for singleton.
}
+ @UsedForTesting
public static RingCharBuffer getInstance() {
return sRingCharBuffer;
}
@@ -93,6 +95,7 @@ public final class Utils {
return ret < 0 ? ret + BUFSIZE : ret;
}
// TODO: accept code points
+ @UsedForTesting
public void push(char c, int x, int y) {
if (!mEnabled) return;
mCharBuf[mEnd] = c;
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 31f616dd9..f7cb4346a 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
@@ -177,7 +178,8 @@ public final class WordComposer {
/**
* Internal method to retrieve reasonable proximity info for a character.
*/
- private void addKeyInfo(final int codePoint, final Keyboard keyboard) {
+ @UsedForTesting
+ public void addKeyInfo(final int codePoint, final Keyboard keyboard) {
final int x, y;
final Key key;
if (keyboard != null && (key = keyboard.getKey(codePoint)) != null) {
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index 83acca874..e1e5e5500 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -258,6 +258,8 @@ public final class FormatSpec {
public final FormatOptions mFormatOptions;
private static final String DICTIONARY_VERSION_ATTRIBUTE = "version";
private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale";
+ private static final String DICTIONARY_ID_ATTRIBUTE = "dictionary";
+ private static final String DICTIONARY_DESCRIPTION_ATTRIBUTE = "description";
public FileHeader(final int headerSize, final DictionaryOptions dictionaryOptions,
final FormatOptions formatOptions) {
mHeaderSize = headerSize;
@@ -274,6 +276,18 @@ public final class FormatSpec {
public String getVersion() {
return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_VERSION_ATTRIBUTE);
}
+
+ // Helper method to get the dictionary ID as a String
+ public String getId() {
+ return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_ID_ATTRIBUTE);
+ }
+
+ // Helper method to get the description
+ public String getDescription() {
+ // TODO: Right now each dictionary file comes with a description in its own language.
+ // It will display as is no matter the device's locale. It should be internationalized.
+ return mDictionaryOptions.mAttributes.get(FileHeader.DICTIONARY_DESCRIPTION_ATTRIBUTE);
+ }
}
private FormatSpec() {
diff --git a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
new file mode 100644
index 000000000..1b893a65d
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2013 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.setup;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+import com.android.inputmethod.compat.IntentCompatUtils;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.Settings;
+
+/**
+ * This class detects the {@link Intent#ACTION_MY_PACKAGE_REPLACED} broadcast intent when this IME
+ * package has been replaced by a newer version of the same package. This class also detects
+ * {@link Intent#ACTION_BOOT_COMPLETED} and {@link Intent#ACTION_USER_INITIALIZE} broadcast intent.
+ *
+ * If this IME has already been installed in the system image and a new version of this IME has
+ * been installed, {@link Intent#ACTION_MY_PACKAGE_REPLACED} is received by this receiver and it
+ * will hide the setup wizard's icon.
+ *
+ * If this IME has already been installed in the data partition and a new version of this IME has
+ * been installed, {@link Intent#ACTION_MY_PACKAGE_REPLACED} is received by this receiver but it
+ * will not hide the setup wizard's icon, and the icon will appear on the launcher.
+ *
+ * If this IME hasn't been installed yet and has been newly installed, no
+ * {@link Intent#ACTION_MY_PACKAGE_REPLACED} will be sent and the setup wizard's icon will appear
+ * on the launcher.
+ *
+ * When the device has been booted, {@link Intent#ACTION_BOOT_COMPLETED} is received by this
+ * receiver and it checks whether the setup wizard's icon should be appeared or not on the launcher
+ * depending on which partition this IME is installed.
+ *
+ * When a multiuser account has been created, {@link Intent#ACTION_USER_INITIALIZE} is received
+ * by this receiver and it checks the whether the setup wizard's icon should be appeared or not on
+ * the launcher depending on which partition this IME is installed.
+ */
+public final class LauncherIconVisibilityManager extends BroadcastReceiver {
+ private static final String TAG = LauncherIconVisibilityManager.class.getSimpleName();
+
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ if (shouldHandleThisIntent(intent, context)) {
+ updateSetupWizardIconVisibility(context);
+ }
+
+ // The process that hosts this broadcast receiver is invoked and remains alive even after
+ // 1) the package has been re-installed, 2) the device has been booted,
+ // 3) a multiuser has been created.
+ // There is no good reason to keep the process alive if this IME isn't a current IME.
+ RichInputMethodManager.init(context);
+ if (!SetupActivity.isThisImeCurrent(context)) {
+ final int myPid = Process.myPid();
+ Log.i(TAG, "Killing my process: pid=" + myPid);
+ Process.killProcess(myPid);
+ }
+ }
+
+ private static boolean shouldHandleThisIntent(final Intent intent, final Context context) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(action)) {
+ Log.i(TAG, "Package has been replaced: " + context.getPackageName());
+ return true;
+ } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ Log.i(TAG, "Boot has been completed");
+ return true;
+ } else if (IntentCompatUtils.has_ACTION_USER_INITIALIZE(intent)) {
+ Log.i(TAG, "User initialize");
+ return true;
+ }
+ return false;
+ }
+
+ public static void updateSetupWizardIconVisibility(final Context context) {
+ final ComponentName setupWizardActivity = new ComponentName(context, SetupActivity.class);
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ final boolean stateHasSet;
+ if (Settings.readShowSetupWizardIcon(prefs, context)) {
+ stateHasSet = setActivityState(context, setupWizardActivity,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+ Log.i(TAG, (stateHasSet ? "Enable activity: " : "Activity has already been enabled: ")
+ + setupWizardActivity);
+ } else {
+ stateHasSet = setActivityState(context, setupWizardActivity,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+ Log.i(TAG, (stateHasSet ? "Disable activity: " : "Activity has already been disabled: ")
+ + setupWizardActivity);
+ }
+ }
+
+ private static boolean setActivityState(final Context context,
+ final ComponentName activityComponent, final int activityState) {
+ final PackageManager pm = context.getPackageManager();
+ final int activityComponentState = pm.getComponentEnabledSetting(activityComponent);
+ if (activityComponentState == activityState) {
+ return false;
+ }
+ pm.setComponentEnabledSetting(
+ activityComponent, activityState, PackageManager.DONT_KILL_APP);
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index fab894584..e009fbc39 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -17,23 +17,341 @@
package com.android.inputmethod.latin.setup;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.Message;
+import android.provider.Settings;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+import com.android.inputmethod.compat.TextViewCompatUtils;
+import com.android.inputmethod.compat.ViewCompatUtils;
+import com.android.inputmethod.latin.CollectionUtils;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
import com.android.inputmethod.latin.SettingsActivity;
+import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
+
+import java.util.HashMap;
public final class SetupActivity extends Activity {
+ private SetupStepIndicatorView mStepIndicatorView;
+ private final SetupStepGroup mSetupSteps = new SetupStepGroup();
+ private static final String STATE_STEP = "step";
+ private int mStepNumber;
+ private static final int STEP_1 = 1;
+ private static final int STEP_2 = 2;
+ private static final int STEP_3 = 3;
+
+ private final SettingsPoolingHandler mHandler = new SettingsPoolingHandler(this);
+
+ static final class SettingsPoolingHandler extends StaticInnerHandlerWrapper<SetupActivity> {
+ private static final int MSG_POLLING_IME_SETTINGS = 0;
+ private static final long IME_SETTINGS_POLLING_INTERVAL = 200;
+
+ public SettingsPoolingHandler(final SetupActivity outerInstance) {
+ super(outerInstance);
+ }
+
+ @Override
+ public void handleMessage(final Message msg) {
+ final SetupActivity setupActivity = getOuterInstance();
+ switch (msg.what) {
+ case MSG_POLLING_IME_SETTINGS:
+ if (SetupActivity.isThisImeEnabled(setupActivity)) {
+ setupActivity.invokeSetupWizardOfThisIme();
+ return;
+ }
+ startPollingImeSettings();
+ break;
+ }
+ }
+
+ public void startPollingImeSettings() {
+ sendMessageDelayed(obtainMessage(MSG_POLLING_IME_SETTINGS),
+ IME_SETTINGS_POLLING_INTERVAL);
+ }
+
+ public void cancelPollingImeSettings() {
+ removeMessages(MSG_POLLING_IME_SETTINGS);
+ }
+ }
+
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ protected void onCreate(final Bundle savedInstanceState) {
+ setTheme(android.R.style.Theme_DeviceDefault_Light_NoActionBar);
super.onCreate(savedInstanceState);
- // TODO: Implement setup wizard.
+ setContentView(R.layout.setup_wizard);
+
+ RichInputMethodManager.init(this);
+
+ if (savedInstanceState == null) {
+ mStepNumber = determineSetupStepNumber();
+ } else {
+ mStepNumber = savedInstanceState.getInt(STATE_STEP);
+ }
+
+ if (mStepNumber == STEP_3) {
+ // This IME already has been enabled and set as current IME.
+ // TODO: Implement tutorial.
+ invokeSettingsOfThisIme();
+ finish();
+ return;
+ }
+
+ // TODO: Use sans-serif-thin font family depending on the system locale white list and
+ // the SDK version.
+ final TextView titleView = (TextView)findViewById(R.id.setup_title);
+ titleView.setText(getString(R.string.setup_title, getString(R.string.english_ime_name)));
+
+ mStepIndicatorView = (SetupStepIndicatorView)findViewById(R.id.setup_step_indicator);
+
+ final SetupStep step1 = new SetupStep(findViewById(R.id.setup_step1),
+ R.string.setup_step1_title, R.string.setup_step1_instruction,
+ R.drawable.ic_settings_language, R.string.language_settings);
+ step1.setAction(new Runnable() {
+ @Override
+ public void run() {
+ invokeLanguageAndInputSettings();
+ mHandler.startPollingImeSettings();
+ }
+ });
+ mSetupSteps.addStep(STEP_1, step1);
+
+ final SetupStep step2 = new SetupStep(findViewById(R.id.setup_step2),
+ R.string.setup_step2_title, R.string.setup_step2_instruction,
+ 0 /* actionIcon */, R.string.select_input_method);
+ step2.setAction(new Runnable() {
+ @Override
+ public void run() {
+ // Invoke input method picker.
+ RichInputMethodManager.getInstance().getInputMethodManager()
+ .showInputMethodPicker();
+ }
+ });
+ mSetupSteps.addStep(STEP_2, step2);
+
+ final SetupStep step3 = new SetupStep(findViewById(R.id.setup_step3),
+ R.string.setup_step3_title, 0 /* instruction */,
+ R.drawable.sym_keyboard_language_switch, R.string.setup_step3_instruction);
+ step3.setAction(new Runnable() {
+ @Override
+ public void run() {
+ invokeSubtypeEnablerOfThisIme();
+ }
+ });
+ mSetupSteps.addStep(STEP_3, step3);
+ }
+
+ private void invokeSetupWizardOfThisIme() {
+ final Intent intent = new Intent();
+ intent.setClass(this, SetupActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ }
+
+ private void invokeSettingsOfThisIme() {
final Intent intent = new Intent();
intent.setClass(this, SettingsActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
- finish();
+ }
+
+ private void invokeLanguageAndInputSettings() {
+ final Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_INPUT_METHOD_SETTINGS);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ startActivity(intent);
+ }
+
+ private void invokeSubtypeEnablerOfThisIme() {
+ final InputMethodInfo imi =
+ RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme();
+ final Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, imi.getId());
+ startActivity(intent);
+ }
+
+ /**
+ * Check if the IME specified by the context is enabled.
+ * Note that {@link RichInputMethodManager} must have been initialized before calling this
+ * method.
+ *
+ * @param context package context of the IME to be checked.
+ * @return true if this IME is enabled.
+ */
+ public static boolean isThisImeEnabled(final Context context) {
+ final String packageName = context.getPackageName();
+ final InputMethodManager imm = RichInputMethodManager.getInstance().getInputMethodManager();
+ for (final InputMethodInfo imi : imm.getEnabledInputMethodList()) {
+ if (packageName.equals(imi.getPackageName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check if the IME specified by the context is the current IME.
+ * Note that {@link RichInputMethodManager} must have been initialized before calling this
+ * method.
+ *
+ * @param context package context of the IME to be checked.
+ * @return true if this IME is the current IME.
+ */
+ public static boolean isThisImeCurrent(final Context context) {
+ final InputMethodInfo myImi =
+ RichInputMethodManager.getInstance().getInputMethodInfoOfThisIme();
+ final String currentImeId = Settings.Secure.getString(
+ context.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+ return myImi.getId().equals(currentImeId);
+ }
+
+ private int determineSetupStepNumber() {
+ mHandler.cancelPollingImeSettings();
+ if (!isThisImeEnabled(this)) {
+ return STEP_1;
+ }
+ if (!isThisImeCurrent(this)) {
+ return STEP_2;
+ }
+ return STEP_3;
+ }
+
+ @Override
+ protected void onSaveInstanceState(final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_STEP, mStepNumber);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(final Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ mStepNumber = savedInstanceState.getInt(STATE_STEP);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mStepNumber = determineSetupStepNumber();
+ }
+
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ mStepNumber = determineSetupStepNumber();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ updateSetupStepView();
+ }
+
+ @Override
+ public void onWindowFocusChanged(final boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (!hasFocus) {
+ return;
+ }
+ mStepNumber = determineSetupStepNumber();
+ updateSetupStepView();
+ }
+
+ private void updateSetupStepView() {
+ final int layoutDirection = ViewCompatUtils.getLayoutDirection(mStepIndicatorView);
+ mStepIndicatorView.setIndicatorPosition(
+ getIndicatorPosition(mStepNumber, mSetupSteps.getTotalStep(), layoutDirection));
+ mSetupSteps.enableStep(mStepNumber);
+ }
+
+ private static float getIndicatorPosition(final int step, final int totalStep,
+ final int layoutDirection) {
+ final float pos = ((step - STEP_1) * 2 + 1) / (float)(totalStep * 2);
+ return (layoutDirection == ViewCompatUtils.LAYOUT_DIRECTION_RTL) ? 1.0f - pos : pos;
+ }
+
+ static final class SetupStep implements View.OnClickListener {
+ private final View mRootView;
+ private final TextView mActionLabel;
+ private Runnable mAction;
+
+ public SetupStep(final View rootView, final int title, final int instruction,
+ final int actionIcon, final int actionLabel) {
+ mRootView = rootView;
+ final Resources res = rootView.getResources();
+ final String applicationName = res.getString(R.string.english_ime_name);
+
+ final TextView titleView = (TextView)rootView.findViewById(R.id.setup_step_title);
+ titleView.setText(res.getString(title, applicationName));
+
+ final TextView instructionView = (TextView)rootView.findViewById(
+ R.id.setup_step_instruction);
+ if (instruction == 0) {
+ instructionView.setVisibility(View.GONE);
+ } else {
+ instructionView.setText(res.getString(instruction, applicationName));
+ }
+
+ mActionLabel = (TextView)rootView.findViewById(R.id.setup_step_action_label);
+ mActionLabel.setText(res.getString(actionLabel));
+ if (actionIcon == 0) {
+ final int paddingEnd = ViewCompatUtils.getPaddingEnd(mActionLabel);
+ ViewCompatUtils.setPaddingRelative(mActionLabel, paddingEnd, 0, paddingEnd, 0);
+ } else {
+ final int overrideColor = res.getColor(R.color.setup_text_action);
+ final Drawable icon = res.getDrawable(actionIcon);
+ icon.setColorFilter(overrideColor, PorterDuff.Mode.MULTIPLY);
+ icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+ TextViewCompatUtils.setCompoundDrawablesRelative(
+ mActionLabel, icon, null, null, null);
+ }
+ }
+
+ public void setEnabled(final boolean enabled) {
+ mRootView.setVisibility(enabled ? View.VISIBLE : View.GONE);
+ }
+
+ public void setAction(final Runnable action) {
+ mActionLabel.setOnClickListener(this);
+ mAction = action;
+ }
+
+ @Override
+ public void onClick(final View v) {
+ if (mAction != null) {
+ mAction.run();
+ }
+ }
+ }
+
+ static final class SetupStepGroup {
+ private final HashMap<Integer, SetupStep> mGroup = CollectionUtils.newHashMap();
+
+ public void addStep(final int stepNo, final SetupStep step) {
+ mGroup.put(stepNo, step);
+ }
+
+ public void enableStep(final int enableStepNo) {
+ for (final Integer stepNo : mGroup.keySet()) {
+ final SetupStep step = mGroup.get(stepNo);
+ step.setEnabled(stepNo == enableStepNo);
+ }
+ }
+
+ public int getTotalStep() {
+ return mGroup.size();
+ }
}
}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java b/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java
new file mode 100644
index 000000000..077a21793
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/setup/SetupStepIndicatorView.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 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.setup;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.inputmethod.latin.R;
+
+public final class SetupStepIndicatorView extends View {
+ private final Path mIndicatorPath = new Path();
+ private final Paint mIndicatorPaint = new Paint();
+ private float mXRatio;
+
+ public SetupStepIndicatorView(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ mIndicatorPaint.setColor(getResources().getColor(R.color.setup_step_background));
+ mIndicatorPaint.setStyle(Paint.Style.FILL);
+ }
+
+ public void setIndicatorPosition(final float xRatio) {
+ mXRatio = xRatio;
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(final Canvas canvas) {
+ super.onDraw(canvas);
+ final int xPos = (int)(getWidth() * mXRatio);
+ final int height = getHeight();
+ mIndicatorPath.rewind();
+ mIndicatorPath.moveTo(xPos, 0);
+ mIndicatorPath.lineTo(xPos + height, height);
+ mIndicatorPath.lineTo(xPos - height, height);
+ mIndicatorPath.close();
+ canvas.drawPath(mIndicatorPath, mIndicatorPaint);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index bc51d5d62..5a29eee4e 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -644,10 +644,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
return false;
}
- public SuggestedWords getSuggestions() {
- return mSuggestedWords;
- }
-
public void clear() {
mSuggestionsStrip.removeAllViews();
removeAllViews();
diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java
index 1a9a720f3..839e2b7ba 100644
--- a/java/src/com/android/inputmethod/research/LogUnit.java
+++ b/java/src/com/android/inputmethod/research/LogUnit.java
@@ -16,7 +16,6 @@
package com.android.inputmethod.research;
-import android.content.SharedPreferences;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.JsonWriter;
@@ -45,7 +44,7 @@ import java.util.List;
* will not violate the user's privacy. Checks for this may include whether other LogUnits have
* been published recently, or whether the LogUnit contains numbers, etc.
*/
-/* package */ class LogUnit {
+public class LogUnit {
private static final String TAG = LogUnit.class.getSimpleName();
private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
@@ -151,10 +150,10 @@ import java.util.List;
continue;
}
// Only retrieve the jsonWriter if we need to. If we don't get this far, then
- // researchLog.getValidJsonWriterLocked() will not ever be called, and the file
- // will not have been opened for writing.
+ // researchLog.getInitializedJsonWriterLocked() will not ever be called, and the
+ // file will not have been opened for writing.
if (jsonWriter == null) {
- jsonWriter = researchLog.getValidJsonWriterLocked();
+ jsonWriter = researchLog.getInitializedJsonWriterLocked();
outputLogUnitStart(jsonWriter, canIncludePrivateData);
}
logStatement.outputToLocked(jsonWriter, mTimeList.get(i), mValuesList.get(i));
diff --git a/java/src/com/android/inputmethod/research/LoggingUtils.java b/java/src/com/android/inputmethod/research/LoggingUtils.java
new file mode 100644
index 000000000..1261d6780
--- /dev/null
+++ b/java/src/com/android/inputmethod/research/LoggingUtils.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 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.research;
+
+import android.view.MotionEvent;
+
+/* package */ class LoggingUtils {
+ private LoggingUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ /* package */ static String getMotionEventActionTypeString(final int actionType) {
+ switch (actionType) {
+ case MotionEvent.ACTION_CANCEL: return "CANCEL";
+ case MotionEvent.ACTION_UP: return "UP";
+ case MotionEvent.ACTION_DOWN: return "DOWN";
+ case MotionEvent.ACTION_POINTER_UP: return "POINTER_UP";
+ case MotionEvent.ACTION_POINTER_DOWN: return "POINTER_DOWN";
+ case MotionEvent.ACTION_MOVE: return "MOVE";
+ case MotionEvent.ACTION_OUTSIDE: return "OUTSIDE";
+ default: return "ACTION_" + actionType;
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/research/MainLogBuffer.java b/java/src/com/android/inputmethod/research/MainLogBuffer.java
index 3a87bf1df..9aa60f859 100644
--- a/java/src/com/android/inputmethod/research/MainLogBuffer.java
+++ b/java/src/com/android/inputmethod/research/MainLogBuffer.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.research;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.Suggest;
import com.android.inputmethod.latin.define.ProductionFlag;
@@ -64,16 +65,11 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
// The size of the n-grams logged. E.g. N_GRAM_SIZE = 2 means to sample bigrams.
public static final int N_GRAM_SIZE = 2;
- // Whether all words should be recorded, leaving unsampled word between bigrams. Useful for
- // testing.
- /* package for test */ static final boolean IS_LOGGING_EVERYTHING = false
- && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
-
- // The number of words between n-grams to omit from the log.
- private static final int DEFAULT_NUMBER_OF_WORDS_BETWEEN_SAMPLES =
- IS_LOGGING_EVERYTHING ? 0 : (DEBUG ? 2 : 18);
-
- private Suggest mSuggest;
+ // TODO: Remove dependence on Suggest, and pass in Dictionary as a parameter to an appropriate
+ // method.
+ private final Suggest mSuggest;
+ @UsedForTesting
+ private Dictionary mDictionaryForTesting;
private boolean mIsStopping = false;
/* package for test */ int mNumWordsBetweenNGrams;
@@ -82,15 +78,25 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
// after a sample is taken.
/* package for test */ int mNumWordsUntilSafeToSample;
- public MainLogBuffer() {
- super(N_GRAM_SIZE + DEFAULT_NUMBER_OF_WORDS_BETWEEN_SAMPLES);
- mNumWordsBetweenNGrams = DEFAULT_NUMBER_OF_WORDS_BETWEEN_SAMPLES;
- final Random random = new Random();
- mNumWordsUntilSafeToSample = DEBUG ? 0 : random.nextInt(mNumWordsBetweenNGrams + 1);
+ public MainLogBuffer(final int wordsBetweenSamples, final int numInitialWordsToIgnore,
+ final Suggest suggest) {
+ super(N_GRAM_SIZE + wordsBetweenSamples);
+ mNumWordsBetweenNGrams = wordsBetweenSamples;
+ mNumWordsUntilSafeToSample = DEBUG ? 0 : numInitialWordsToIgnore;
+ mSuggest = suggest;
}
- public void setSuggest(final Suggest suggest) {
- mSuggest = suggest;
+ @UsedForTesting
+ /* package for test */ void setDictionaryForTesting(final Dictionary dictionary) {
+ mDictionaryForTesting = dictionary;
+ }
+
+ private Dictionary getDictionary() {
+ if (mDictionaryForTesting != null) {
+ return mDictionaryForTesting;
+ }
+ if (mSuggest == null || !mSuggest.hasMainDictionary()) return null;
+ return mSuggest.getMainDictionary();
}
public void resetWordCounter() {
@@ -114,7 +120,7 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
*/
private boolean isSafeNGram(final ArrayList<LogUnit> logUnits, final int minNGramSize) {
// Bypass privacy checks when debugging.
- if (IS_LOGGING_EVERYTHING) {
+ if (ResearchLogger.IS_LOGGING_EVERYTHING) {
if (mIsStopping) {
return true;
}
@@ -137,16 +143,13 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
if (mNumWordsUntilSafeToSample > 0) {
return false;
}
- if (mSuggest == null || !mSuggest.hasMainDictionary()) {
- // Main dictionary is unavailable. Since we cannot check it, we cannot tell if a
- // word is out-of-vocabulary or not. Therefore, we must judge the entire buffer
- // contents to potentially pose a privacy risk.
- return false;
- }
// Reload the dictionary in case it has changed (e.g., because the user has changed
// languages).
- final Dictionary dictionary = mSuggest.getMainDictionary();
+ final Dictionary dictionary = getDictionary();
if (dictionary == null) {
+ // Main dictionary is unavailable. Since we cannot check it, we cannot tell if a
+ // word is out-of-vocabulary or not. Therefore, we must judge the entire buffer
+ // contents to potentially pose a privacy risk.
return false;
}
@@ -220,10 +223,10 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
final boolean canIncludePrivateData);
@Override
- protected void shiftOutWords(int numWords) {
- int oldNumActualWords = getNumActualWords();
+ protected void shiftOutWords(final int numWords) {
+ final int oldNumActualWords = getNumActualWords();
super.shiftOutWords(numWords);
- int numWordsShifted = oldNumActualWords - getNumActualWords();
+ final int numWordsShifted = oldNumActualWords - getNumActualWords();
mNumWordsUntilSafeToSample -= numWordsShifted;
if (DEBUG) {
Log.d(TAG, "wordsUntilSafeToSample now at " + mNumWordsUntilSafeToSample);
diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java
index 5114977d8..9016e23b3 100644
--- a/java/src/com/android/inputmethod/research/ResearchLog.java
+++ b/java/src/com/android/inputmethod/research/ResearchLog.java
@@ -38,12 +38,19 @@ import java.util.concurrent.TimeUnit;
/**
* Logs the use of the LatinIME keyboard.
*
- * This class logs operations on the IME keyboard, including what the user has typed.
- * Data is stored locally in a file in app-specific storage.
+ * This class logs operations on the IME keyboard, including what the user has typed. Data is
+ * written to a {@link JsonWriter}, which will write to a local file.
+ *
+ * The JsonWriter is created on-demand by calling {@link #getInitializedJsonWriterLocked}.
+ *
+ * This class uses an executor to perform file-writing operations on a separate thread. It also
+ * tries to avoid creating unnecessary files if there is nothing to write. It also handles
+ * flushing, making sure it happens, but not too frequently.
*
* This functionality is off by default. See {@link ProductionFlag#IS_EXPERIMENTAL}.
*/
public class ResearchLog {
+ // TODO: Automatically initialize the JsonWriter rather than requiring the caller to manage it.
private static final String TAG = ResearchLog.class.getSimpleName();
private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
private static final long FLUSH_DELAY_IN_MS = 1000 * 5;
@@ -87,6 +94,12 @@ public class ResearchLog {
mContext = context;
}
+ /**
+ * Waits for any publication requests to finish and closes the {@link JsonWriter} used for
+ * output.
+ *
+ * See class comment for details about {@code JsonWriter} construction.
+ */
public synchronized void close(final Runnable onClosed) {
mExecutor.submit(new Callable<Object>() {
@Override
@@ -94,20 +107,15 @@ public class ResearchLog {
try {
if (mHasWrittenData) {
mJsonWriter.endArray();
- mJsonWriter.flush();
- mJsonWriter.close();
- if (DEBUG) {
- Log.d(TAG, "wrote log to " + mFile);
- }
mHasWrittenData = false;
- } else {
- if (DEBUG) {
- Log.d(TAG, "close() called, but no data, not outputting");
- }
+ }
+ mJsonWriter.flush();
+ mJsonWriter.close();
+ if (DEBUG) {
+ Log.d(TAG, "wrote log to " + mFile);
}
} catch (Exception e) {
- Log.d(TAG, "error when closing ResearchLog:");
- e.printStackTrace();
+ Log.d(TAG, "error when closing ResearchLog:", e);
} finally {
if (mFile != null && mFile.exists()) {
mFile.setWritable(false, false);
@@ -125,6 +133,12 @@ public class ResearchLog {
private boolean mIsAbortSuccessful;
+ /**
+ * Waits for publication requests to finish, closes the {@link JsonWriter}, but then deletes the
+ * backing file used for output.
+ *
+ * See class comment for details about {@code JsonWriter} construction.
+ */
public synchronized void abort() {
mExecutor.submit(new Callable<Object>() {
@Override
@@ -184,6 +198,12 @@ public class ResearchLog {
mFlushFuture = mExecutor.schedule(mFlushCallable, FLUSH_DELAY_IN_MS, TimeUnit.MILLISECONDS);
}
+ /**
+ * Queues up {@code logUnit} to be published in the background.
+ *
+ * @param logUnit the {@link LogUnit} to be published
+ * @param canIncludePrivateData whether private data in the LogUnit should be included
+ */
public synchronized void publish(final LogUnit logUnit, final boolean canIncludePrivateData) {
try {
mExecutor.submit(new Callable<Object>() {
@@ -206,29 +226,39 @@ public class ResearchLog {
* Return a JsonWriter for this ResearchLog. It is initialized the first time this method is
* called. The cached value is returned in future calls.
*/
- public JsonWriter getValidJsonWriterLocked() {
+ public JsonWriter getInitializedJsonWriterLocked() {
+ if (mJsonWriter != NULL_JSON_WRITER || mFile == null) return mJsonWriter;
try {
- if (mJsonWriter == NULL_JSON_WRITER && mFile != null) {
- final FileOutputStream fos =
- mContext.openFileOutput(mFile.getName(), Context.MODE_PRIVATE);
- mJsonWriter = new JsonWriter(new BufferedWriter(new OutputStreamWriter(fos)));
- mJsonWriter.beginArray();
+ final JsonWriter jsonWriter = createJsonWriter(mContext, mFile);
+ if (jsonWriter != null) {
+ jsonWriter.beginArray();
+ mJsonWriter = jsonWriter;
mHasWrittenData = true;
}
- } catch (IOException e) {
- e.printStackTrace();
- Log.w(TAG, "Error in JsonWriter; disabling logging");
+ } catch (final IOException e) {
+ Log.w(TAG, "Error in JsonWriter; disabling logging", e);
try {
mJsonWriter.close();
- } catch (IllegalStateException e1) {
+ } catch (final IllegalStateException e1) {
// Assume that this is just the json not being terminated properly.
// Ignore
- } catch (IOException e1) {
- e1.printStackTrace();
+ } catch (final IOException e1) {
+ Log.w(TAG, "Error in closing JsonWriter; disabling logging", e1);
} finally {
mJsonWriter = NULL_JSON_WRITER;
}
}
return mJsonWriter;
}
+
+ /**
+ * Create the JsonWriter to write the ResearchLog to.
+ *
+ * This method may be overriden in testing to redirect the output.
+ */
+ /* package for test */ JsonWriter createJsonWriter(final Context context, final File file)
+ throws IOException {
+ return new JsonWriter(new BufferedWriter(new OutputStreamWriter(
+ context.openFileOutput(file.getName(), Context.MODE_PRIVATE))));
+ }
}
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index 45212913e..e705ddda1 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -88,6 +88,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Random;
import java.util.UUID;
/**
@@ -121,31 +122,36 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// field holds a channel name, the developer does not have to re-enter it when using the
// feedback mechanism to generate multiple tests.
private static final boolean FEEDBACK_DIALOG_SHOULD_PRESERVE_TEXT_FIELD = false;
- public static final boolean DEFAULT_USABILITY_STUDY_MODE = false;
/* package */ static boolean sIsLogging = false;
private static final int OUTPUT_FORMAT_VERSION = 5;
private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
- private static final String PREF_RESEARCH_HAS_SEEN_SPLASH = "pref_research_has_seen_splash";
/* package */ static final String LOG_FILENAME_PREFIX = "researchLog";
private static final String LOG_FILENAME_SUFFIX = ".txt";
/* package */ static final String USER_RECORDING_FILENAME_PREFIX = "recording";
private static final String USER_RECORDING_FILENAME_SUFFIX = ".txt";
private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
new SimpleDateFormat("yyyyMMddHHmmssS", Locale.US);
+ // Whether all words should be recorded, leaving unsampled word between bigrams. Useful for
+ // testing.
+ /* package for test */ static final boolean IS_LOGGING_EVERYTHING = false
+ && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
+ // The number of words between n-grams to omit from the log.
+ private static final int NUMBER_OF_WORDS_BETWEEN_SAMPLES =
+ IS_LOGGING_EVERYTHING ? 0 : (DEBUG ? 2 : 18);
+
// Whether to show an indicator on the screen that logging is on. Currently a very small red
// dot in the lower right hand corner. Most users should not notice it.
private static final boolean IS_SHOWING_INDICATOR = true;
// Change the default indicator to something very visible. Currently two red vertical bars on
// either side of they keyboard.
private static final boolean IS_SHOWING_INDICATOR_CLEARLY = false ||
- (MainLogBuffer.IS_LOGGING_EVERYTHING && ProductionFlag.IS_EXPERIMENTAL_DEBUG);
+ (IS_LOGGING_EVERYTHING && ProductionFlag.IS_EXPERIMENTAL_DEBUG);
// FEEDBACK_WORD_BUFFER_SIZE should add 1 because it must also hold the feedback LogUnit itself.
public static final int FEEDBACK_WORD_BUFFER_SIZE = (Integer.MAX_VALUE - 1) + 1;
// constants related to specific log points
private static final String WHITESPACE_SEPARATORS = " \t\n\r";
private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
- private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid";
private static final String PREF_RESEARCH_SAVED_CHANNEL = "pref_research_saved_channel";
private static final ResearchLogger sInstance = new ResearchLogger();
@@ -153,7 +159,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private static String sAllowedAccountDomain = null;
// to write to a different filename, e.g., for testing, set mFile before calling start()
/* package */ File mFilesDir;
- /* package */ String mUUIDString;
/* package */ ResearchLog mMainResearchLog;
// mFeedbackLog records all events for the session, private or not (excepting
// passwords). It is written to permanent storage only if the user explicitly commands
@@ -199,7 +204,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private Intent mUploadIntent;
private Intent mUploadNowIntent;
- private LogUnit mCurrentLogUnit = new LogUnit();
+ /* package for test */ LogUnit mCurrentLogUnit = new LogUnit();
// Gestured or tapped words may be committed after the gesture of the next word has started.
// To ensure that the gesture data of the next word is not associated with the previous word,
@@ -228,50 +233,44 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
return sInstance;
}
- public void init(final LatinIME latinIME, final KeyboardSwitcher keyboardSwitcher) {
+ public void init(final LatinIME latinIME, final KeyboardSwitcher keyboardSwitcher,
+ final Suggest suggest) {
assert latinIME != null;
- if (latinIME == null) {
- Log.w(TAG, "IMS is null; logging is off");
- } else {
- mFilesDir = latinIME.getFilesDir();
- if (mFilesDir == null || !mFilesDir.exists()) {
- Log.w(TAG, "IME storage directory does not exist.");
- }
- }
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(latinIME);
- if (prefs != null) {
- mUUIDString = getUUID(prefs);
- if (!prefs.contains(PREF_USABILITY_STUDY_MODE)) {
- Editor e = prefs.edit();
- e.putBoolean(PREF_USABILITY_STUDY_MODE, DEFAULT_USABILITY_STUDY_MODE);
- e.apply();
- }
- sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
- prefs.registerOnSharedPreferenceChangeListener(this);
-
- final long lastCleanupTime = prefs.getLong(PREF_LAST_CLEANUP_TIME, 0L);
- final long now = System.currentTimeMillis();
- if (lastCleanupTime + DURATION_BETWEEN_DIR_CLEANUP_IN_MS < now) {
- final long timeHorizon = now - MAX_LOGFILE_AGE_IN_MS;
- cleanupLoggingDir(mFilesDir, timeHorizon);
- Editor e = prefs.edit();
- e.putLong(PREF_LAST_CLEANUP_TIME, now);
- e.apply();
- }
+ mLatinIME = latinIME;
+ mFilesDir = latinIME.getFilesDir();
+ if (mFilesDir == null || !mFilesDir.exists()) {
+ Log.w(TAG, "IME storage directory does not exist. Cannot start logging.");
+ return;
}
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(latinIME);
+ mPrefs.registerOnSharedPreferenceChangeListener(this);
+
+ // Initialize fields from preferences
+ sIsLogging = ResearchSettings.readResearchLoggerEnabledFlag(mPrefs);
+
+ // Initialize fields from resources
final Resources res = latinIME.getResources();
sAccountType = res.getString(R.string.research_account_type);
sAllowedAccountDomain = res.getString(R.string.research_allowed_account_domain);
- mLatinIME = latinIME;
- mPrefs = prefs;
+
+ // Cleanup logging directory
+ // TODO: Move this and other file-related components to separate file.
+ final long lastCleanupTime = mPrefs.getLong(PREF_LAST_CLEANUP_TIME, 0L);
+ final long now = System.currentTimeMillis();
+ if (now - lastCleanupTime > DURATION_BETWEEN_DIR_CLEANUP_IN_MS) {
+ final long timeHorizon = now - MAX_LOGFILE_AGE_IN_MS;
+ cleanupLoggingDir(mFilesDir, timeHorizon);
+ mPrefs.edit().putLong(PREF_LAST_CLEANUP_TIME, now).apply();
+ }
+
+ // Initialize external services
mUploadIntent = new Intent(mLatinIME, UploaderService.class);
mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true);
- mReplayer.setKeyboardSwitcher(keyboardSwitcher);
-
if (ProductionFlag.IS_EXPERIMENTAL) {
scheduleUploadingService(mLatinIME);
}
+ mReplayer.setKeyboardSwitcher(keyboardSwitcher);
}
/**
@@ -313,14 +312,16 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mMainKeyboardView = null;
}
- private boolean hasSeenSplash() {
- return mPrefs.getBoolean(PREF_RESEARCH_HAS_SEEN_SPLASH, false);
+ public void onDestroy() {
+ if (mPrefs != null) {
+ mPrefs.unregisterOnSharedPreferenceChangeListener(this);
+ }
}
private Dialog mSplashDialog = null;
private void maybeShowSplashScreen() {
- if (hasSeenSplash()) {
+ if (ResearchSettings.readHasSeenSplash(mPrefs)) {
return;
}
if (mSplashDialog != null && mSplashDialog.isShowing()) {
@@ -373,32 +374,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
public void onUserLoggingConsent() {
- setLoggingAllowed(true);
if (mPrefs == null) {
- return;
+ mPrefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
+ if (mPrefs == null) return;
}
- final Editor e = mPrefs.edit();
- e.putBoolean(PREF_RESEARCH_HAS_SEEN_SPLASH, true);
- e.apply();
+ sIsLogging = true;
+ ResearchSettings.writeResearchLoggerEnabledFlag(mPrefs, true);
+ ResearchSettings.writeHasSeenSplash(mPrefs, true);
restart();
}
- private void setLoggingAllowed(boolean enableLogging) {
- if (mPrefs == null) {
- return;
- }
- Editor e = mPrefs.edit();
- e.putBoolean(PREF_USABILITY_STUDY_MODE, enableLogging);
- e.apply();
- sIsLogging = enableLogging;
- }
-
private static int sLogFileCounter = 0;
private File createLogFile(final File filesDir) {
final StringBuilder sb = new StringBuilder();
sb.append(LOG_FILENAME_PREFIX).append('-');
- sb.append(mUUIDString).append('-');
+ final String uuid = ResearchSettings.readResearchLoggerUuid(mPrefs);
+ sb.append(uuid).append('-');
sb.append(TIMESTAMP_DATEFORMAT.format(new Date())).append('-');
// Sometimes logFiles are created within milliseconds of each other. Append a counter to
// separate these.
@@ -416,7 +408,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private File createUserRecordingFile(final File filesDir) {
final StringBuilder sb = new StringBuilder();
sb.append(USER_RECORDING_FILENAME_PREFIX).append('-');
- sb.append(mUUIDString).append('-');
+ final String uuid = ResearchSettings.readResearchLoggerUuid(mPrefs);
+ sb.append(uuid).append('-');
sb.append(TIMESTAMP_DATEFORMAT.format(new Date()));
sb.append(USER_RECORDING_FILENAME_SUFFIX);
return new File(filesDir, sb.toString());
@@ -458,17 +451,15 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// Log.w(TAG, "not in usability mode; not logging");
return;
}
- if (mFilesDir == null || !mFilesDir.exists()) {
- Log.w(TAG, "IME storage directory does not exist. Cannot start logging.");
- return;
- }
if (mMainLogBuffer == null) {
mMainResearchLog = new ResearchLog(createLogFile(mFilesDir), mLatinIME);
- mMainLogBuffer = new MainLogBuffer() {
+ final int numWordsToIgnore = new Random().nextInt(NUMBER_OF_WORDS_BETWEEN_SAMPLES + 1);
+ mMainLogBuffer = new MainLogBuffer(NUMBER_OF_WORDS_BETWEEN_SAMPLES, numWordsToIgnore,
+ mSuggest) {
@Override
protected void publish(final ArrayList<LogUnit> logUnits,
boolean canIncludePrivateData) {
- canIncludePrivateData |= MainLogBuffer.IS_LOGGING_EVERYTHING;
+ canIncludePrivateData |= IS_LOGGING_EVERYTHING;
final int length = logUnits.size();
for (int i = 0; i < length; i++) {
final LogUnit logUnit = logUnits.get(i);
@@ -487,7 +478,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
};
- mMainLogBuffer.setSuggest(mSuggest);
}
if (mFeedbackLogBuffer == null) {
resetFeedbackLogging();
@@ -564,7 +554,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
@Override
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
if (key == null || prefs == null) {
return;
}
@@ -586,7 +576,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
presentFeedbackDialog(latinIME);
}
- public void presentFeedbackDialog(LatinIME latinIME) {
+ public void presentFeedbackDialog(final LatinIME latinIME) {
if (isMakingUserRecording()) {
saveRecording();
}
@@ -818,9 +808,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
if (mPrefs == null) {
return;
}
- final Editor e = mPrefs.edit();
- e.putString(PREF_RESEARCH_SAVED_CHANNEL, channelName);
- e.apply();
+ mPrefs.edit().putString(PREF_RESEARCH_SAVED_CHANNEL, channelName).apply();
}
}
@@ -835,10 +823,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mInFeedbackDialog = false;
}
- public void initSuggest(Suggest suggest) {
+ public void initSuggest(final Suggest suggest) {
mSuggest = suggest;
+ // MainLogBuffer has out-of-date Suggest object. Need to close it down and create a new
+ // one.
if (mMainLogBuffer != null) {
- mMainLogBuffer.setSuggest(mSuggest);
+ stop();
+ start();
}
}
@@ -1127,18 +1118,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
}
- private static String getUUID(final SharedPreferences prefs) {
- String uuidString = prefs.getString(PREF_RESEARCH_LOGGER_UUID_STRING, null);
- if (null == uuidString) {
- UUID uuid = UUID.randomUUID();
- uuidString = uuid.toString();
- Editor editor = prefs.edit();
- editor.putString(PREF_RESEARCH_LOGGER_UUID_STRING, uuidString);
- editor.apply();
- }
- return uuidString;
- }
-
private String scrubWord(String word) {
final Dictionary dictionary = getDictionary();
if (dictionary == null) {
@@ -1185,12 +1164,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
0);
final Integer versionCode = packageInfo.versionCode;
final String versionName = packageInfo.versionName;
+ final String uuid = ResearchSettings.readResearchLoggerUuid(researchLogger.mPrefs);
researchLogger.enqueueEvent(LOGSTATEMENT_LATIN_IME_ON_START_INPUT_VIEW_INTERNAL,
- researchLogger.mUUIDString, editorInfo.packageName,
- Integer.toHexString(editorInfo.inputType),
+ uuid, editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId,
Build.DISPLAY, Build.MODEL, prefs, versionCode, versionName,
- OUTPUT_FORMAT_VERSION, MainLogBuffer.IS_LOGGING_EVERYTHING,
+ OUTPUT_FORMAT_VERSION, IS_LOGGING_EVERYTHING,
ProductionFlag.IS_EXPERIMENTAL_DEBUG);
} catch (NameNotFoundException e) {
e.printStackTrace();
@@ -1226,17 +1205,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
public static void mainKeyboardView_processMotionEvent(final MotionEvent me, final int action,
final long eventTime, final int index, final int id, final int x, final int y) {
if (me != null) {
- final String actionString;
- switch (action) {
- case MotionEvent.ACTION_CANCEL: actionString = "CANCEL"; break;
- case MotionEvent.ACTION_UP: actionString = "UP"; break;
- case MotionEvent.ACTION_DOWN: actionString = "DOWN"; break;
- case MotionEvent.ACTION_POINTER_UP: actionString = "POINTER_UP"; break;
- case MotionEvent.ACTION_POINTER_DOWN: actionString = "POINTER_DOWN"; break;
- case MotionEvent.ACTION_MOVE: actionString = "MOVE"; break;
- case MotionEvent.ACTION_OUTSIDE: actionString = "OUTSIDE"; break;
- default: actionString = "ACTION_" + action; break;
- }
+ final String actionString = LoggingUtils.getMotionEventActionTypeString(action);
final ResearchLogger researchLogger = getInstance();
researchLogger.enqueueEvent(LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT,
actionString, false /* IS_LOGGING_RELATED */, MotionEvent.obtain(me));
diff --git a/java/src/com/android/inputmethod/research/ResearchSettings.java b/java/src/com/android/inputmethod/research/ResearchSettings.java
new file mode 100644
index 000000000..11e9ac77a
--- /dev/null
+++ b/java/src/com/android/inputmethod/research/ResearchSettings.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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.research;
+
+import android.content.SharedPreferences;
+
+import java.util.UUID;
+
+public final class ResearchSettings {
+ public static final String PREF_RESEARCH_LOGGER_UUID = "pref_research_logger_uuid";
+ public static final String PREF_RESEARCH_LOGGER_ENABLED_FLAG =
+ "pref_research_logger_enabled_flag";
+ public static final String PREF_RESEARCH_LOGGER_HAS_SEEN_SPLASH =
+ "pref_research_logger_has_seen_splash";
+
+ private ResearchSettings() {
+ // Intentional empty constructor for singleton.
+ }
+
+ public static String readResearchLoggerUuid(final SharedPreferences prefs) {
+ if (prefs.contains(PREF_RESEARCH_LOGGER_UUID)) {
+ return prefs.getString(PREF_RESEARCH_LOGGER_UUID, null);
+ }
+ // Generate a random string as uuid if not yet set
+ final String newUuid = UUID.randomUUID().toString();
+ prefs.edit().putString(PREF_RESEARCH_LOGGER_UUID, newUuid).apply();
+ return newUuid;
+ }
+
+ public static boolean readResearchLoggerEnabledFlag(final SharedPreferences prefs) {
+ return prefs.getBoolean(PREF_RESEARCH_LOGGER_ENABLED_FLAG, false);
+ }
+
+ public static void writeResearchLoggerEnabledFlag(final SharedPreferences prefs,
+ final boolean isEnabled) {
+ prefs.edit().putBoolean(PREF_RESEARCH_LOGGER_ENABLED_FLAG, isEnabled).apply();
+ }
+
+ public static boolean readHasSeenSplash(final SharedPreferences prefs) {
+ return prefs.getBoolean(PREF_RESEARCH_LOGGER_HAS_SEEN_SPLASH, false);
+ }
+
+ public static void writeHasSeenSplash(final SharedPreferences prefs,
+ final boolean hasSeenSplash) {
+ prefs.edit().putBoolean(PREF_RESEARCH_LOGGER_HAS_SEEN_SPLASH, hasSeenSplash).apply();
+ }
+}
diff --git a/java/src/com/android/inputmethod/research/Uploader.java b/java/src/com/android/inputmethod/research/Uploader.java
new file mode 100644
index 000000000..df495a88d
--- /dev/null
+++ b/java/src/com/android/inputmethod/research/Uploader.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 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.research;
+
+import android.Manifest;
+import android.app.AlarmManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.BatteryManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.define.ProductionFlag;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Manages the uploading of ResearchLog files.
+ */
+public final class Uploader {
+ private static final String TAG = Uploader.class.getSimpleName();
+ private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
+ // Set IS_INHIBITING_AUTO_UPLOAD to true for local testing
+ private static final boolean IS_INHIBITING_AUTO_UPLOAD = false
+ && ProductionFlag.IS_EXPERIMENTAL_DEBUG; // Force false for non-debug builds
+ private static final int BUF_SIZE = 1024 * 8;
+
+ private final Context mContext;
+ private final File mFilesDir;
+ private final URL mUrl;
+
+ public Uploader(final Context context) {
+ mContext = context;
+ mFilesDir = context.getFilesDir();
+
+ final String urlString = context.getString(R.string.research_logger_upload_url);
+ if (TextUtils.isEmpty(urlString)) {
+ mUrl = null;
+ return;
+ }
+ URL url = null;
+ try {
+ url = new URL(urlString);
+ } catch (final MalformedURLException e) {
+ Log.e(TAG, "Bad URL for uploading", e);
+ }
+ mUrl = url;
+ }
+
+ public boolean isPossibleToUpload() {
+ return hasUploadingPermission() && mUrl != null && !IS_INHIBITING_AUTO_UPLOAD;
+ }
+
+ private boolean hasUploadingPermission() {
+ final PackageManager packageManager = mContext.getPackageManager();
+ return packageManager.checkPermission(Manifest.permission.INTERNET,
+ mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED;
+ }
+
+ public boolean isConvenientToUpload() {
+ return isExternallyPowered() && hasWifiConnection();
+ }
+
+ private boolean isExternallyPowered() {
+ final Intent intent = mContext.registerReceiver(null, new IntentFilter(
+ Intent.ACTION_BATTERY_CHANGED));
+ final int pluggedState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ return pluggedState == BatteryManager.BATTERY_PLUGGED_AC
+ || pluggedState == BatteryManager.BATTERY_PLUGGED_USB;
+ }
+
+ private boolean hasWifiConnection() {
+ final ConnectivityManager manager =
+ (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ return wifiInfo.isConnected();
+ }
+
+ public void doUpload() {
+ if (mFilesDir == null) {
+ return;
+ }
+ final File[] files = mFilesDir.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(final File pathname) {
+ return pathname.getName().startsWith(ResearchLogger.LOG_FILENAME_PREFIX)
+ && !pathname.canWrite();
+ }
+ });
+ for (final File file : files) {
+ uploadFile(file);
+ }
+ }
+
+ private void uploadFile(final File file) {
+ if (DEBUG) {
+ Log.d(TAG, "attempting upload of " + file.getAbsolutePath());
+ }
+ final int contentLength = (int) file.length();
+ HttpURLConnection connection = null;
+ InputStream fileInputStream = null;
+ try {
+ fileInputStream = new FileInputStream(file);
+ connection = (HttpURLConnection) mUrl.openConnection();
+ connection.setRequestMethod("PUT");
+ connection.setDoOutput(true);
+ connection.setFixedLengthStreamingMode(contentLength);
+ final OutputStream outputStream = connection.getOutputStream();
+ uploadContents(fileInputStream, outputStream);
+ if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ Log.d(TAG, "upload failed: " + connection.getResponseCode());
+ final InputStream netInputStream = connection.getInputStream();
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(
+ netInputStream));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ Log.d(TAG, "| " + reader.readLine());
+ }
+ reader.close();
+ return;
+ }
+ file.delete();
+ if (DEBUG) {
+ Log.d(TAG, "upload successful");
+ }
+ } catch (final IOException e) {
+ Log.e(TAG, "Exception uploading file", e);
+ } finally {
+ if (fileInputStream != null) {
+ try {
+ fileInputStream.close();
+ } catch (final IOException e) {
+ Log.e(TAG, "Exception closing uploaded file", e);
+ }
+ }
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
+
+ private static void uploadContents(final InputStream is, final OutputStream os)
+ throws IOException {
+ // TODO: Switch to NIO.
+ final byte[] buf = new byte[BUF_SIZE];
+ int numBytesRead;
+ while ((numBytesRead = is.read(buf)) != -1) {
+ os.write(buf, 0, numBytesRead);
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/research/UploaderService.java b/java/src/com/android/inputmethod/research/UploaderService.java
index 89c67fbb2..26b651056 100644
--- a/java/src/com/android/inputmethod/research/UploaderService.java
+++ b/java/src/com/android/inputmethod/research/UploaderService.java
@@ -16,189 +16,44 @@
package com.android.inputmethod.research;
-import android.Manifest;
import android.app.AlarmManager;
import android.app.IntentService;
-import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.BatteryManager;
import android.os.Bundle;
-import android.util.Log;
-import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.define.ProductionFlag;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-
+/**
+ * Service to invoke the uploader.
+ *
+ * Can be regularly invoked, invoked on boot, etc.
+ */
public final class UploaderService extends IntentService {
private static final String TAG = UploaderService.class.getSimpleName();
private static final boolean DEBUG = false && ProductionFlag.IS_EXPERIMENTAL_DEBUG;
- // Set IS_INHIBITING_AUTO_UPLOAD to true for local testing
- private static final boolean IS_INHIBITING_AUTO_UPLOAD = false
- && ProductionFlag.IS_EXPERIMENTAL_DEBUG; // Force false in production
public static final long RUN_INTERVAL = AlarmManager.INTERVAL_HOUR;
public static final String EXTRA_UPLOAD_UNCONDITIONALLY = UploaderService.class.getName()
+ ".extra.UPLOAD_UNCONDITIONALLY";
- private static final int BUF_SIZE = 1024 * 8;
protected static final int TIMEOUT_IN_MS = 1000 * 4;
- private boolean mCanUpload;
- private File mFilesDir;
- private URL mUrl;
-
public UploaderService() {
super("Research Uploader Service");
}
@Override
- public void onCreate() {
- super.onCreate();
-
- mCanUpload = false;
- mFilesDir = null;
- mUrl = null;
-
- final PackageManager packageManager = getPackageManager();
- final boolean hasPermission = packageManager.checkPermission(Manifest.permission.INTERNET,
- getPackageName()) == PackageManager.PERMISSION_GRANTED;
- if (!hasPermission) {
- return;
- }
-
- try {
- final String urlString = getString(R.string.research_logger_upload_url);
- if (urlString == null || urlString.equals("")) {
- return;
- }
- mFilesDir = getFilesDir();
- mUrl = new URL(urlString);
- mCanUpload = true;
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- if (!mCanUpload) {
- return;
- }
- boolean isUploadingUnconditionally = false;
- Bundle bundle = intent.getExtras();
- if (bundle != null && bundle.containsKey(EXTRA_UPLOAD_UNCONDITIONALLY)) {
- isUploadingUnconditionally = bundle.getBoolean(EXTRA_UPLOAD_UNCONDITIONALLY);
- }
- doUpload(isUploadingUnconditionally);
- }
-
- private boolean isExternallyPowered() {
- final Intent intent = registerReceiver(null, new IntentFilter(
- Intent.ACTION_BATTERY_CHANGED));
- final int pluggedState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
- return pluggedState == BatteryManager.BATTERY_PLUGGED_AC
- || pluggedState == BatteryManager.BATTERY_PLUGGED_USB;
- }
-
- private boolean hasWifiConnection() {
- final ConnectivityManager manager =
- (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- final NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- return wifiInfo.isConnected();
- }
-
- private void doUpload(final boolean isUploadingUnconditionally) {
- if (!isUploadingUnconditionally && (!isExternallyPowered() || !hasWifiConnection()
- || IS_INHIBITING_AUTO_UPLOAD)) {
- return;
- }
- if (mFilesDir == null) {
- return;
- }
- final File[] files = mFilesDir.listFiles(new FileFilter() {
- @Override
- public boolean accept(File pathname) {
- return pathname.getName().startsWith(ResearchLogger.LOG_FILENAME_PREFIX)
- && !pathname.canWrite();
- }
- });
- boolean success = true;
- if (files.length == 0) {
- success = false;
- }
- for (final File file : files) {
- if (!uploadFile(file)) {
- success = false;
- }
+ protected void onHandleIntent(final Intent intent) {
+ final Uploader uploader = new Uploader(this);
+ if (!uploader.isPossibleToUpload()) return;
+ if (isUploadingUnconditionally(intent.getExtras()) || uploader.isConvenientToUpload()) {
+ uploader.doUpload();
}
}
- private boolean uploadFile(File file) {
- if (DEBUG) {
- Log.d(TAG, "attempting upload of " + file.getAbsolutePath());
- }
- boolean success = false;
- final int contentLength = (int) file.length();
- HttpURLConnection connection = null;
- InputStream fileInputStream = null;
- try {
- fileInputStream = new FileInputStream(file);
- connection = (HttpURLConnection) mUrl.openConnection();
- connection.setRequestMethod("PUT");
- connection.setDoOutput(true);
- connection.setFixedLengthStreamingMode(contentLength);
- final OutputStream os = connection.getOutputStream();
- final byte[] buf = new byte[BUF_SIZE];
- int numBytesRead;
- while ((numBytesRead = fileInputStream.read(buf)) != -1) {
- os.write(buf, 0, numBytesRead);
- if (DEBUG) {
- Log.d(TAG, new String(buf));
- }
- }
- if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
- Log.d(TAG, "upload failed: " + connection.getResponseCode());
- InputStream netInputStream = connection.getInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(netInputStream));
- String line;
- while ((line = reader.readLine()) != null) {
- Log.d(TAG, "| " + reader.readLine());
- }
- reader.close();
- return success;
- }
- file.delete();
- success = true;
- if (DEBUG) {
- Log.d(TAG, "upload successful");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (fileInputStream != null) {
- try {
- fileInputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (connection != null) {
- connection.disconnect();
- }
+ private boolean isUploadingUnconditionally(final Bundle bundle) {
+ if (bundle == null) return false;
+ if (bundle.containsKey(EXTRA_UPLOAD_UNCONDITIONALLY)) {
+ return bundle.getBoolean(EXTRA_UPLOAD_UNCONDITIONALLY);
}
- return success;
+ return false;
}
}
diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/char_utils.cpp
index f1148f4d4..8d917ea74 100644
--- a/native/jni/src/char_utils.cpp
+++ b/native/jni/src/char_utils.cpp
@@ -1070,12 +1070,14 @@ const unsigned short BASE_CHARS[BASE_CHARS_SIZE] = {
/* U+0418 */ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
// U+0419: Manually changed from 0418 to 0419
/* U+0420 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
- /* U+0428 */ 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ /* U+0428 */ 0x0428, 0x0429, 0x042C, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
+ // U+042A: Manually changed from 042A to 042C
/* U+0430 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
/* U+0438 */ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
// U+0439: Manually changed from 0438 to 0439
/* U+0440 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
- /* U+0448 */ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ /* U+0448 */ 0x0448, 0x0449, 0x044C, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
+ // U+044A: Manually changed from 044A to 044C
/* U+0450 */ 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456,
/* U+0458 */ 0x0458, 0x0459, 0x045A, 0x045B, 0x043A, 0x0438, 0x0443, 0x045F,
/* U+0460 */ 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467,
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index d4bd4aa00..0ae02d506 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -190,11 +190,11 @@ bool Correction::needsToPrune() const {
}
inline static bool isEquivalentChar(ProximityType type) {
- return type == EQUIVALENT_CHAR;
+ return type == MATCH_CHAR;
}
inline static bool isProximityCharOrEquivalentChar(ProximityType type) {
- return type == EQUIVALENT_CHAR || type == NEAR_PROXIMITY_CHAR;
+ return type == MATCH_CHAR || type == PROXIMITY_CHAR;
}
Correction::CorrectionType Correction::processCharAndCalcState(const int c, const bool isTerminal) {
@@ -214,14 +214,14 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
bool incremented = false;
if (mLastCharExceeded && mInputIndex == mInputSize - 1) {
// TODO: Do not check the proximity if EditDistance exceeds the threshold
- const ProximityType matchId = mProximityInfoState.getMatchedProximityId(
+ const ProximityType matchId = mProximityInfoState.getProximityType(
mInputIndex, c, true, &proximityIndex);
if (isEquivalentChar(matchId)) {
mLastCharExceeded = false;
--mExcessiveCount;
mDistances[mOutputIndex] =
mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, 0);
- } else if (matchId == NEAR_PROXIMITY_CHAR) {
+ } else if (matchId == PROXIMITY_CHAR) {
mLastCharExceeded = false;
--mExcessiveCount;
++mProximityCount;
@@ -268,7 +268,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
bool secondTransposing = false;
if (mTransposedCount % 2 == 1) {
- if (isEquivalentChar(mProximityInfoState.getMatchedProximityId(
+ if (isEquivalentChar(mProximityInfoState.getProximityType(
mInputIndex - 1, c, false))) {
++mTransposedCount;
secondTransposing = true;
@@ -299,16 +299,16 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
: (noCorrectionsHappenedSoFar && mProximityCount == 0);
ProximityType matchedProximityCharId = secondTransposing
- ? EQUIVALENT_CHAR
- : mProximityInfoState.getMatchedProximityId(
+ ? MATCH_CHAR
+ : mProximityInfoState.getProximityType(
mInputIndex, c, checkProximityChars, &proximityIndex);
- if (UNRELATED_CHAR == matchedProximityCharId
+ if (SUBSTITUTION_CHAR == matchedProximityCharId
|| ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
if (canTryCorrection && mOutputIndex > 0
&& mCorrectionStates[mOutputIndex].mProximityMatching
&& mCorrectionStates[mOutputIndex].mExceeding
- && isEquivalentChar(mProximityInfoState.getMatchedProximityId(
+ && isEquivalentChar(mProximityInfoState.getProximityType(
mInputIndex, mWord[mOutputIndex - 1], false))) {
if (DEBUG_CORRECTION
&& (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputSize)
@@ -327,12 +327,12 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
// Here, we are doing something equivalent to matchedProximityCharId,
// but we already know that "excessive char correction" just happened
// so that we just need to check "mProximityCount == 0".
- matchedProximityCharId = mProximityInfoState.getMatchedProximityId(
+ matchedProximityCharId = mProximityInfoState.getProximityType(
mInputIndex, c, mProximityCount == 0, &proximityIndex);
}
}
- if (UNRELATED_CHAR == matchedProximityCharId
+ if (SUBSTITUTION_CHAR == matchedProximityCharId
|| ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
if (ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
mAdditionalProximityMatching = true;
@@ -344,10 +344,10 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
if (mInputIndex < mInputSize - 1 && mOutputIndex > 0 && mTransposedCount > 0
&& !mCorrectionStates[mOutputIndex].mTransposing
&& mCorrectionStates[mOutputIndex - 1].mTransposing
- && isEquivalentChar(mProximityInfoState.getMatchedProximityId(
+ && isEquivalentChar(mProximityInfoState.getProximityType(
mInputIndex, mWord[mOutputIndex - 1], false))
&& isEquivalentChar(
- mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
+ mProximityInfoState.getProximityType(mInputIndex + 1, c, false))) {
// Conversion t->e
// Example:
// occaisional -> occa sional
@@ -359,7 +359,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
&& !mCorrectionStates[mOutputIndex].mTransposing
&& mCorrectionStates[mOutputIndex - 1].mTransposing
&& isEquivalentChar(
- mProximityInfoState.getMatchedProximityId(mInputIndex - 1, c, false))) {
+ mProximityInfoState.getProximityType(mInputIndex - 1, c, false))) {
// Conversion t->s
// Example:
// chcolate -> chocolate
@@ -371,7 +371,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
&& mCorrectionStates[mOutputIndex].mProximityMatching
&& mCorrectionStates[mOutputIndex].mSkipping
&& isEquivalentChar(
- mProximityInfoState.getMatchedProximityId(mInputIndex - 1, c, false))) {
+ mProximityInfoState.getProximityType(mInputIndex - 1, c, false))) {
// Conversion p->s
// Note: This logic tries saving cases like contrst --> contrast -- "a" is one of
// proximity chars of "s", but it should rather be handled as a skipped char.
@@ -383,7 +383,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
&& mCorrectionStates[mOutputIndex].mSkipping
&& mCorrectionStates[mOutputIndex].mAdditionalProximityMatching
&& isProximityCharOrEquivalentChar(
- mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
+ mProximityInfoState.getProximityType(mInputIndex + 1, c, false))) {
// Conversion s->a
incrementInputIndex();
--mSkippedCount;
@@ -392,7 +392,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
mDistances[mOutputIndex] = ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO;
} else if ((mExceeding || mTransposing) && mInputIndex - 1 < mInputSize
&& isEquivalentChar(
- mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
+ mProximityInfoState.getProximityType(mInputIndex + 1, c, false))) {
// 1.2. Excessive or transpose correction
if (mTransposing) {
++mTransposedCount;
@@ -455,7 +455,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
mMatching = true;
++mEquivalentCharCount;
mDistances[mOutputIndex] = mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, 0);
- } else if (NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
+ } else if (PROXIMITY_CHAR == matchedProximityCharId) {
mProximityMatching = true;
++mProximityCount;
mDistances[mOutputIndex] =
@@ -614,7 +614,7 @@ inline static bool isUpperCase(unsigned short c) {
multiplyIntCapped(matchWeight, &finalFreq);
}
- if (proximityInfoState->getMatchedProximityId(0, word[0], true) == UNRELATED_CHAR) {
+ if (proximityInfoState->getProximityType(0, word[0], true) == SUBSTITUTION_CHAR) {
multiplyRate(FIRST_CHAR_DIFFERENT_DEMOTION_RATE, &finalFreq);
}
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index 34f794d84..f0d62102f 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -119,7 +119,7 @@ class Correction {
// proximity info state
void initInputParams(const ProximityInfo *proximityInfo, const int *inputCodes,
const int inputSize, const int *xCoordinates, const int *yCoordinates) {
- mProximityInfoState.initInputParams(0, MAX_POINT_TO_KEY_LENGTH,
+ mProximityInfoState.initInputParams(0, static_cast<float>(MAX_VALUE_FOR_WEIGHTING),
proximityInfo, inputCodes, inputSize, xCoordinates, yCoordinates, 0, 0, false);
}
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index a1fdae7a4..0aedc287f 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -214,6 +214,8 @@ static inline void prof_out(void) {
#define DEBUG_SAMPLING_POINTS false
#define DEBUG_POINTS_PROBABILITY false
#define DEBUG_DOUBLE_LETTER false
+#define DEBUG_CACHE false
+#define DEBUG_DUMP_ERROR false
#ifdef FLAG_FULL_DBG
#define DEBUG_GEO_FULL true
@@ -237,6 +239,8 @@ static inline void prof_out(void) {
#define DEBUG_SAMPLING_POINTS false
#define DEBUG_POINTS_PROBABILITY false
#define DEBUG_DOUBLE_LETTER false
+#define DEBUG_CACHE false
+#define DEBUG_DUMP_ERROR false
#define DEBUG_GEO_FULL false
@@ -271,7 +275,7 @@ static inline void prof_out(void) {
#define NOT_A_CODE_POINT (-1)
#define NOT_A_DISTANCE (-1)
#define NOT_A_COORDINATE (-1)
-#define EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO (-2)
+#define MATCH_CHAR_WITHOUT_DISTANCE_INFO (-2)
#define PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO (-3)
#define ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO (-4)
#define NOT_AN_INDEX (-1)
@@ -283,6 +287,7 @@ static inline void prof_out(void) {
#define CALIBRATE_SCORE_BY_TOUCH_COORDINATES true
#define SUGGEST_MULTIPLE_WORDS true
+#define SUGGEST_INTERFACE_OUTPUT_SCALE 1000000.0f
// The following "rate"s are used as a multiplier before dividing by 100, so they are in percent.
#define WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE 80
@@ -336,8 +341,9 @@ static inline void prof_out(void) {
#define MAX_DEPTH_MULTIPLIER 3
#define FIRST_WORD_INDEX 0
-// Max Distance between point to key
-#define MAX_POINT_TO_KEY_LENGTH 10000000
+// Max value for length, distance and probability which are used in weighting
+// TODO: Remove
+#define MAX_VALUE_FOR_WEIGHTING 10000000
// The max number of the keys in one keyboard layout
#define MAX_KEY_COUNT_IN_A_KEYBOARD 64
@@ -390,13 +396,15 @@ template<typename T> AK_FORCE_INLINE const T &max(const T &a, const T &b) { retu
// Used as a return value for character comparison
typedef enum {
// Same char, possibly with different case or accent
- EQUIVALENT_CHAR,
+ MATCH_CHAR,
// It is a char located nearby on the keyboard
- NEAR_PROXIMITY_CHAR,
+ PROXIMITY_CHAR,
+ // Additional proximity char which can differ by language.
+ ADDITIONAL_PROXIMITY_CHAR,
+ // It is a substitution char
+ SUBSTITUTION_CHAR,
// It is an unrelated char
UNRELATED_CHAR,
- // Additional proximity char which can differ by language.
- ADDITIONAL_PROXIMITY_CHAR
} ProximityType;
typedef enum {
@@ -404,4 +412,19 @@ typedef enum {
A_DOUBLE_LETTER,
A_STRONG_DOUBLE_LETTER
} DoubleLetterLevel;
+
+typedef enum {
+ CT_MATCH,
+ CT_PROXIMITY,
+ CT_ADDITIONAL_PROXIMITY,
+ CT_SUBSTITUTION,
+ CT_OMISSION,
+ CT_INSERTION,
+ CT_TRANSPOSITION,
+ CT_SPACE_SUBSTITUTION,
+ CT_SPACE_OMISSION,
+ CT_COMPLETION,
+ CT_TERMINAL,
+ CT_NEW_WORD,
+} CorrectionType;
#endif // LATINIME_DEFINES_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index 81eb0b37d..74b5e0131 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -204,6 +204,6 @@ int ProximityInfo::getKeyKeyDistanceG(const int keyId0, const int keyId1) const
if (keyId0 >= 0 && keyId1 >= 0) {
return mKeyKeyDistancesG[keyId0][keyId1];
}
- return MAX_POINT_TO_KEY_LENGTH;
+ return MAX_VALUE_FOR_WEIGHTING;
}
} // namespace latinime
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index 22bbdf165..57a175d2c 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -70,7 +70,7 @@ class ProximityInfo {
int getKeyCenterYOfKeyIdG(int keyId) const;
int getKeyKeyDistanceG(int keyId0, int keyId1) const;
- void AK_FORCE_INLINE initializeProximities(const int *const inputCodes,
+ AK_FORCE_INLINE void initializeProximities(const int *const inputCodes,
const int *const inputXCoordinates, const int *const inputYCoordinates,
const int inputSize, int *allInputCodes) const {
ProximityInfoUtils::initializeProximities(inputCodes, inputXCoordinates, inputYCoordinates,
@@ -79,10 +79,14 @@ class ProximityInfo {
KEY_COUNT, mLocaleStr, &mCodeToKeyMap, allInputCodes);
}
- int AK_FORCE_INLINE getKeyIndexOf(const int c) const {
+ AK_FORCE_INLINE int getKeyIndexOf(const int c) const {
return ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, c, &mCodeToKeyMap);
}
+ AK_FORCE_INLINE bool isCodePointOnKeyboard(const int codePoint) const {
+ return getKeyIndexOf(codePoint) != NOT_AN_INDEX;
+ }
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfo);
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index bdbf8b170..fe1c43320 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -36,6 +36,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
mIsContinuationPossible = ProximityInfoStateUtils::checkAndReturnIsContinuationPossible(
inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
&mSampledInputYs, &mSampledTimes, &mSampledInputIndice);
+ if (DEBUG_DICT) {
+ AKLOGI("isContinuationPossible = %s", (mIsContinuationPossible ? "true" : "false"));
+ }
mProximityInfo = proximityInfo;
mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData();
@@ -153,36 +156,26 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
}
}
-// TODO: Remove the "scale" parameter
// This function basically converts from a length to an edit distance. Accordingly, it's obviously
// wrong to compare with mMaxPointToKeyLength.
float ProximityInfoState::getPointToKeyLength(
- const int inputIndex, const int codePoint, const float scale) const {
+ const int inputIndex, const int codePoint) const {
const int keyId = mProximityInfo->getKeyIndexOf(codePoint);
if (keyId != NOT_AN_INDEX) {
const int index = inputIndex * mProximityInfo->getKeyCount() + keyId;
- return min(mSampledDistanceCache_G[index] * scale, mMaxPointToKeyLength);
+ return min(mSampledDistanceCache_G[index], mMaxPointToKeyLength);
}
if (isSkippableCodePoint(codePoint)) {
return 0.0f;
}
// If the char is not a key on the keyboard then return the max length.
- return MAX_POINT_TO_KEY_LENGTH;
-}
-
-float ProximityInfoState::getPointToKeyLength_G(const int inputIndex, const int codePoint) const {
- return getPointToKeyLength(inputIndex, codePoint, 1.0f);
+ return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
}
-// TODO: Remove the "scale" parameter
float ProximityInfoState::getPointToKeyByIdLength(
- const int inputIndex, const int keyId, const float scale) const {
+ const int inputIndex, const int keyId) const {
return ProximityInfoStateUtils::getPointToKeyByIdLength(mMaxPointToKeyLength,
- &mSampledDistanceCache_G, mProximityInfo->getKeyCount(), inputIndex, keyId, scale);
-}
-
-float ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const int keyId) const {
- return getPointToKeyByIdLength(inputIndex, keyId, 1.0f);
+ &mSampledDistanceCache_G, mProximityInfo->getKeyCount(), inputIndex, keyId);
}
// In the following function, c is the current character of the dictionary word currently examined.
@@ -190,41 +183,42 @@ float ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const in
// the same position. We want to see if c is in it: if so, then the word contains at that position
// a character close to what the user typed.
// What the user typed is actually the first character of the array.
-// proximityIndex is a pointer to the variable where getMatchedProximityId returns the index of c
+// proximityIndex is a pointer to the variable where getProximityType returns the index of c
// in the proximity chars of the input index.
// Notice : accented characters do not have a proximity list, so they are alone in their list. The
// non-accented version of the character should be considered "close", but not the other keys close
// to the non-accented version.
-ProximityType ProximityInfoState::getMatchedProximityId(const int index, const int c,
+ProximityType ProximityInfoState::getProximityType(const int index, const int codePoint,
const bool checkProximityChars, int *proximityIndex) const {
const int *currentCodePoints = getProximityCodePointsAt(index);
const int firstCodePoint = currentCodePoints[0];
- const int baseLowerC = toBaseLowerCase(c);
+ const int baseLowerC = toBaseLowerCase(codePoint);
// The first char in the array is what user typed. If it matches right away, that means the
// user typed that same char for this pos.
- if (firstCodePoint == baseLowerC || firstCodePoint == c) {
- return EQUIVALENT_CHAR;
+ if (firstCodePoint == baseLowerC || firstCodePoint == codePoint) {
+ return MATCH_CHAR;
}
- if (!checkProximityChars) return UNRELATED_CHAR;
+ if (!checkProximityChars) return SUBSTITUTION_CHAR;
// If the non-accented, lowercased version of that first character matches c, then we have a
// non-accented version of the accented character the user typed. Treat it as a close char.
if (toBaseLowerCase(firstCodePoint) == baseLowerC) {
- return NEAR_PROXIMITY_CHAR;
+ return PROXIMITY_CHAR;
}
// Not an exact nor an accent-alike match: search the list of close keys
int j = 1;
while (j < MAX_PROXIMITY_CHARS_SIZE
&& currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
- const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
+ const bool matched = (currentCodePoints[j] == baseLowerC
+ || currentCodePoints[j] == codePoint);
if (matched) {
if (proximityIndex) {
*proximityIndex = j;
}
- return NEAR_PROXIMITY_CHAR;
+ return PROXIMITY_CHAR;
}
++j;
}
@@ -233,7 +227,8 @@ ProximityType ProximityInfoState::getMatchedProximityId(const int index, const i
++j;
while (j < MAX_PROXIMITY_CHARS_SIZE
&& currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
- const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
+ const bool matched = (currentCodePoints[j] == baseLowerC
+ || currentCodePoints[j] == codePoint);
if (matched) {
if (proximityIndex) {
*proximityIndex = j;
@@ -243,7 +238,22 @@ ProximityType ProximityInfoState::getMatchedProximityId(const int index, const i
++j;
}
}
- // Was not included, signal this as an unrelated character.
+ // Was not included, signal this as a substitution character.
+ return SUBSTITUTION_CHAR;
+}
+
+ProximityType ProximityInfoState::getProximityTypeG(const int index, const int codePoint) const {
+ if (!isUsed()) {
+ return UNRELATED_CHAR;
+ }
+ const int lowerCodePoint = toLowerCase(codePoint);
+ const int baseLowerCodePoint = toBaseCodePoint(lowerCodePoint);
+ for (int i = 0; i < static_cast<int>(mSampledSearchKeyVectors[index].size()); ++i) {
+ if (mSampledSearchKeyVectors[index][i] == lowerCodePoint
+ || mSampledSearchKeyVectors[index][i] == baseLowerCodePoint) {
+ return MATCH_CHAR;
+ }
+ }
return UNRELATED_CHAR;
}
@@ -294,6 +304,6 @@ float ProximityInfoState::getProbability(const int index, const int keyIndex) co
if (it != mCharProbabilities[index].end()) {
return it->second;
}
- return static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+ return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
}
} // namespace latinime
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
index c4cbd582d..224240b00 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/proximity_info_state.h
@@ -147,14 +147,14 @@ class ProximityInfoState {
return mIsContinuationPossible;
}
- float getPointToKeyByIdLength(const int inputIndex, const int keyId, const float scale) const;
float getPointToKeyByIdLength(const int inputIndex, const int keyId) const;
- float getPointToKeyLength(const int inputIndex, const int codePoint, const float scale) const;
- float getPointToKeyLength_G(const int inputIndex, const int codePoint) const;
+ float getPointToKeyLength(const int inputIndex, const int codePoint) const;
- ProximityType getMatchedProximityId(const int index, const int c,
+ ProximityType getProximityType(const int index, const int codePoint,
const bool checkProximityChars, int *proximityIndex = 0) const;
+ ProximityType getProximityTypeG(const int index, const int codePoint) const;
+
const std::vector<int> *getSearchKeyVector(const int index) const {
return &mSampledSearchKeyVectors[index];
}
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/proximity_info_state_utils.cpp
index 2bf327fcc..ccb28bc8c 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/proximity_info_state_utils.cpp
@@ -209,7 +209,7 @@ namespace latinime {
* ProximityInfoParams::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
} else {
normalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
- (j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO :
+ (j == 0) ? MATCH_CHAR_WITHOUT_DISTANCE_INFO :
PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO;
}
if (DEBUG_PROXIMITY_CHARS) {
@@ -634,25 +634,17 @@ namespace latinime {
return getAngleDiff(previousDirection, nextDirection);
}
-// TODO: Remove the "scale" parameter
// This function basically converts from a length to an edit distance. Accordingly, it's obviously
// wrong to compare with mMaxPointToKeyLength.
/* static */ float ProximityInfoStateUtils::getPointToKeyByIdLength(const float maxPointToKeyLength,
const std::vector<float> *const SampledDistanceCache_G, const int keyCount,
- const int inputIndex, const int keyId, const float scale) {
+ const int inputIndex, const int keyId) {
if (keyId != NOT_AN_INDEX) {
const int index = inputIndex * keyCount + keyId;
- return min((*SampledDistanceCache_G)[index] * scale, maxPointToKeyLength);
+ return min((*SampledDistanceCache_G)[index], maxPointToKeyLength);
}
// If the char is not a key on the keyboard then return the max length.
- return static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
-}
-
-/* static */ float ProximityInfoStateUtils::getPointToKeyByIdLength(const float maxPointToKeyLength,
- const std::vector<float> *const SampledDistanceCache_G, const int keyCount,
- const int inputIndex, const int keyId) {
- return getPointToKeyByIdLength(
- maxPointToKeyLength, SampledDistanceCache_G, keyCount, inputIndex, keyId, 1.0f);
+ return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
}
// Updates probabilities of aligning to some keys and skipping.
@@ -678,7 +670,7 @@ namespace latinime {
const float currentAngle = getPointAngle(sampledInputXs, sampledInputYs, i);
const float speedRate = (*sampledSpeedRates)[i];
- float nearestKeyDistance = static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+ float nearestKeyDistance = static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
for (int j = 0; j < keyCount; ++j) {
if ((*SampledNearKeySets)[i].test(j)) {
const float distance = getPointToKeyByIdLength(
@@ -1016,7 +1008,7 @@ namespace latinime {
float sumLogProbability = 0.0f;
// TODO: Current implementation is greedy algorithm. DP would be efficient for many cases.
for (int i = 0; i < sampledInputSize && index < MAX_WORD_LENGTH - 1; ++i) {
- float minLogProbability = static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+ float minLogProbability = static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
int character = NOT_AN_INDEX;
for (hash_map_compat<int, float>::const_iterator it = (*charProbabilities)[i].begin();
it != (*charProbabilities)[i].end(); ++it) {
diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/proximity_info_state_utils.h
index d55730aca..a7f4a3425 100644
--- a/native/jni/src/proximity_info_state_utils.h
+++ b/native/jni/src/proximity_info_state_utils.h
@@ -81,9 +81,6 @@ class ProximityInfoStateUtils {
std::vector<std::vector<int> > *sampledSearchKeyVectors);
static float getPointToKeyByIdLength(const float maxPointToKeyLength,
const std::vector<float> *const SampledDistanceCache_G, const int keyCount,
- const int inputIndex, const int keyId, const float scale);
- static float getPointToKeyByIdLength(const float maxPointToKeyLength,
- const std::vector<float> *const SampledDistanceCache_G, const int keyCount,
const int inputIndex, const int keyId);
static void initGeometricDistanceInfos(const ProximityInfo *const proximityInfo,
const int sampledInputSize, const int lastSavedInputSize,
diff --git a/native/jni/src/proximity_info_utils.h b/native/jni/src/proximity_info_utils.h
index 51cafba2c..71c97e325 100644
--- a/native/jni/src/proximity_info_utils.h
+++ b/native/jni/src/proximity_info_utils.h
@@ -226,7 +226,7 @@ class ProximityInfoUtils {
const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights,
const int keyId, const int x, const int y) {
// NOT_A_ID is -1, but return whenever < 0 just in case
- if (keyId < 0) return MAX_POINT_TO_KEY_LENGTH;
+ if (keyId < 0) return MAX_VALUE_FOR_WEIGHTING;
const int left = keyXCoordinates[keyId];
const int top = keyYCoordinates[keyId];
const int right = left + keyWidths[keyId];
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
index 005f8b279..333b60277 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
@@ -74,15 +74,22 @@ public class InputLogicTestsNonEnglish extends InputTestsBase {
public void testWordThenSpaceDisplaysPredictions() {
final String WORD_TO_TYPE = "beaujolais ";
final String EXPECTED_RESULT = "nouveau";
- changeLanguage("fr");
- type(WORD_TO_TYPE);
- sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
- runMessages();
- final SuggestionStripView suggestionStripView =
- (SuggestionStripView)mInputView.findViewById(R.id.suggestion_strip_view);
- final SuggestedWords suggestedWords = suggestionStripView.getSuggestions();
- assertEquals("type word then type space yields predictions for French",
- EXPECTED_RESULT, suggestedWords.getWord(0));
+ final boolean defaultNextWordPredictionOption =
+ mLatinIME.getResources().getBoolean(R.bool.config_default_next_word_prediction);
+ final boolean previousNextWordPredictionOption =
+ setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, true,
+ defaultNextWordPredictionOption);
+ try {
+ changeLanguage("fr");
+ type(WORD_TO_TYPE);
+ sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+ runMessages();
+ assertEquals("type word then type space yields predictions for French",
+ EXPECTED_RESULT, mLatinIME.getFirstSuggestedWord());
+ } finally {
+ setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, previousNextWordPredictionOption,
+ defaultNextWordPredictionOption);
+ }
}
public void testAutoCorrectForGerman() {
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
index 1e2036662..abfaf3062 100644
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -189,7 +189,7 @@ public class SubtypeLocaleTests extends AndroidTestCase {
SubtypeLocale.getSubtypeDisplayName(FR_CA));
assertEquals("de ", "Deutsch",
SubtypeLocale.getSubtypeDisplayName(DE));
- assertEquals("zz ", "Pas de langue (QWERTY)",
+ assertEquals("zz ", "Aucune langue (QWERTY)",
SubtypeLocale.getSubtypeDisplayName(ZZ));
return null;
}
@@ -301,7 +301,7 @@ public class SubtypeLocaleTests extends AndroidTestCase {
// fr azerty F Français
// fr_CA qwerty F Français (Canada)
// de qwertz F Allemand
- // zz qwerty F Pas de langue (QWERTY)
+ // zz qwerty F Aucune langue (QWERTY)
// fr qwertz T Français (QWERTZ)
// de qwerty T Allemand (QWERTY)
// en_US azerty T Anglais (États-Unis) (AZERTY) exception
@@ -325,7 +325,7 @@ public class SubtypeLocaleTests extends AndroidTestCase {
SubtypeLocale.getSubtypeDisplayNameInSystemLocale(FR_CA));
assertEquals("de ", "Allemand",
SubtypeLocale.getSubtypeDisplayNameInSystemLocale(DE));
- assertEquals("zz ", "Pas de langue (QWERTY)",
+ assertEquals("zz ", "Aucune langue (QWERTY)",
SubtypeLocale.getSubtypeDisplayNameInSystemLocale(ZZ));
return null;
}
diff --git a/tools/maketext/res/values-ar/donottranslate-more-keys.xml b/tools/maketext/res/values-ar/donottranslate-more-keys.xml
index f10139e09..cace240b6 100644
--- a/tools/maketext/res/values-ar/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-ar/donottranslate-more-keys.xml
@@ -99,31 +99,11 @@
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 -->
+ U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -->
<string name="more_keys_for_less_than">!fixedColumnOrder!3,&#x2039;|&#x203A;,&#x2264;|&#x2265;,&#x00AB;|&#x00BB;</string>
<string name="more_keys_for_greater_than">!fixedColumnOrder!3,&#x203A;|&#x2039;,&#x2265;|&#x2264;,&#x00BB;|&#x00AB;</string>
- <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
- <!-- <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string> -->
- <string name="more_keys_for_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
- <!-- 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string> -->
- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- <!-- U+00A2: "¢" CENT SIGN
- U+00A3: "£" POUND SIGN
- U+20AC: "€" EURO SIGN
- U+00A5: "¥" YEN SIGN
- U+20B1: "₱" PESO SIGN
- U+FDFC: "﷼" RIAL SIGN -->
- <string name="more_keys_for_currency_dollar">&#x00A2;,&#x00A3;,&#x20AC;,&#x00A5;,&#x20B1;,&#xFDFC;</string>
+ <string name="single_angle_quotes">!text/single_laqm_raqm_rtl</string>
+ <string name="double_angle_quotes">!text/double_laqm_raqm_rtl</string>
<!-- U+0655: "ٕ" ARABIC HAMZA BELOW
U+0654: "ٔ" ARABIC HAMZA ABOVE
U+0652: "ْ" ARABIC SUKUN
diff --git a/tools/maketext/res/values-be/donottranslate-more-keys.xml b/tools/maketext/res/values-be/donottranslate-more-keys.xml
index c8f216742..4723503f1 100644
--- a/tools/maketext/res/values-be/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-be/donottranslate-more-keys.xml
@@ -37,4 +37,6 @@
U+0411: "Б" CYRILLIC CAPITAL LETTER BE
U+0412: "В" CYRILLIC CAPITAL LETTER VE -->
<string name="label_to_alpha_key">&#x0410;&#x0411;&#x0412;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-bg/donottranslate-more-keys.xml b/tools/maketext/res/values-bg/donottranslate-more-keys.xml
index e7570df87..5262133de 100644
--- a/tools/maketext/res/values-bg/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-bg/donottranslate-more-keys.xml
@@ -23,4 +23,6 @@
U+0411: "Б" CYRILLIC CAPITAL LETTER BE
U+0412: "В" CYRILLIC CAPITAL LETTER VE -->
<string name="label_to_alpha_key">&#x0410;&#x0411;&#x0412;</string>
+ <!-- single_quotes of Bulgarian is default single_quotes_right_left. -->
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-cs/donottranslate-more-keys.xml b/tools/maketext/res/values-cs/donottranslate-more-keys.xml
index 9af6794df..5ce1d3bc8 100644
--- a/tools/maketext/res/values-cs/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-cs/donottranslate-more-keys.xml
@@ -84,4 +84,8 @@
U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE -->
<string name="more_keys_for_z">&#x017E;,&#x017A;,&#x017C;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-da/donottranslate-more-keys.xml b/tools/maketext/res/values-da/donottranslate-more-keys.xml
index acc0c534d..cbaf9f497 100644
--- a/tools/maketext/res/values-da/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-da/donottranslate-more-keys.xml
@@ -68,4 +68,8 @@
<string name="more_keys_for_nordic_row2_10">&#x00E4;</string>
<!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS -->
<string name="more_keys_for_nordic_row2_11">&#x00F6;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-de/donottranslate-more-keys.xml b/tools/maketext/res/values-de/donottranslate-more-keys.xml
index 181a3b5c2..9dc8717ec 100644
--- a/tools/maketext/res/values-de/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-de/donottranslate-more-keys.xml
@@ -55,4 +55,8 @@
<!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE -->
<string name="more_keys_for_n">&#x00F1;,&#x0144;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-et/donottranslate-more-keys.xml b/tools/maketext/res/values-et/donottranslate-more-keys.xml
index 69cf654a6..d037044bd 100644
--- a/tools/maketext/res/values-et/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-et/donottranslate-more-keys.xml
@@ -111,4 +111,6 @@
<string name="keylabel_for_nordic_row2_11">&#x00E4;</string>
<!-- U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE -->
<string name="more_keys_for_nordic_row2_10">&#x00F5;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-fa/donottranslate-more-keys.xml b/tools/maketext/res/values-fa/donottranslate-more-keys.xml
index 6acdd41a8..7c8496d6f 100644
--- a/tools/maketext/res/values-fa/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-fa/donottranslate-more-keys.xml
@@ -106,33 +106,11 @@
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 -->
+ U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -->
<string name="more_keys_for_less_than">!fixedColumnOrder!3,&#x2039;|&#x203A;,&#x2264;|&#x2265;,&lt;|&gt;</string>
<string name="more_keys_for_greater_than">!fixedColumnOrder!3,&#x203A;|&#x2039;,&#x2265;|&#x2264;,&gt;|&lt;</string>
- <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
- <!-- <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string> -->
- <string name="more_keys_for_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,\",\'</string>
- <!-- 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string> -->
- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- <!-- U+FDFC: "﷼" RIAL SIGN
- U+060B: "؋" AFGHANI SIGN
- U+00A2: "¢" CENT SIGN
- U+00A3: "£" POUND SIGN
- U+20AC: "€" EURO SIGN
- U+00A5: "¥" YEN SIGN
- U+20B1: "₱" PESO SIGN -->
- <string name="keylabel_for_currency_generic">&#xFDFC;</string>
- <string name="more_keys_for_currency_generic">$,&#x00A2;,&#x20AC;,&#x00A3;,&#x00A5;,&#x20B1;,&#x060B;</string>
+ <string name="single_angle_quotes">!text/single_laqm_raqm_rtl</string>
+ <string name="double_angle_quotes">!text/double_laqm_raqm_rtl</string>
<!-- U+0655: "ٕ" ARABIC HAMZA BELOW
U+0652: "ْ" ARABIC SUKUN
U+0651: "ّ" ARABIC SHADDA
diff --git a/tools/maketext/res/values-hr/donottranslate-more-keys.xml b/tools/maketext/res/values-hr/donottranslate-more-keys.xml
index 9b4005d0d..022bd2a87 100644
--- a/tools/maketext/res/values-hr/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-hr/donottranslate-more-keys.xml
@@ -35,4 +35,8 @@
<string name="more_keys_for_c">&#x010D;,&#x0107;,&#x00E7;</string>
<!-- U+0111: "đ" LATIN SMALL LETTER D WITH STROKE -->
<string name="more_keys_for_d">&#x0111;</string>
+ <string name="single_quotes">!text/single_9qm_rqm</string>
+ <string name="double_quotes">!text/double_9qm_rqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-hu/donottranslate-more-keys.xml b/tools/maketext/res/values-hu/donottranslate-more-keys.xml
index 48259104b..ce2f5d057 100644
--- a/tools/maketext/res/values-hu/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-hu/donottranslate-more-keys.xml
@@ -59,4 +59,8 @@
U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
U+016B: "ū" LATIN SMALL LETTER U WITH MACRON -->
<string name="more_keys_for_u">&#x00FA;,&#x00FC;,&#x0171;,&#x00FB;,&#x00F9;,&#x016B;</string>
+ <string name="single_quotes">!text/single_9qm_rqm</string>
+ <string name="double_quotes">!text/double_9qm_rqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-is/donottranslate-more-keys.xml b/tools/maketext/res/values-is/donottranslate-more-keys.xml
index 284aae930..4b4d986b8 100644
--- a/tools/maketext/res/values-is/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-is/donottranslate-more-keys.xml
@@ -70,4 +70,6 @@
<string name="keylabel_for_nordic_row2_10">&#x00E6;</string>
<!-- U+00FE: "þ" LATIN SMALL LETTER THORN -->
<string name="keylabel_for_nordic_row2_11">&#x00FE;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-iw/donottranslate-more-keys.xml b/tools/maketext/res/values-iw/donottranslate-more-keys.xml
index 20b4c6af7..64d42272f 100644
--- a/tools/maketext/res/values-iw/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-iw/donottranslate-more-keys.xml
@@ -37,24 +37,18 @@
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+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -->
+ <string name="more_keys_for_less_than">!fixedColumnOrder!3,&#x2039;|&#x203A;,&#x2264;|&#x2265;,&#x00AB;|&#x00BB;</string>
+ <string name="more_keys_for_greater_than">!fixedColumnOrder!3,&#x203A;|&#x2039;,&#x2265;|&#x2264;,&#x00BB;|&#x00AB;</string>
+ <!-- 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 -->
- <string name="more_keys_for_less_than">!fixedColumnOrder!3,&#x2039;|&#x203A;,&#x2264;|&#x2265;,&#x00AB;|&#x00BB;</string>
- <string name="more_keys_for_greater_than">!fixedColumnOrder!3,&#x203A;|&#x2039;,&#x2265;|&#x2264;,&#x00BB;|&#x00AB;</string>
- <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
- <!-- <string name="more_keys_for_double_quote">&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string> -->
- <string name="more_keys_for_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
- <!-- 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;|&#x00BB;,&#x00BB|&#x00AB;;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string> -->
- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- <!-- U+20AA: "₪" NEW SHEQEL SIGN -->
- <string name="keylabel_for_currency_generic">&#x20AA;</string>
+ U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
+ <string name="single_quotes">&#x2018;,&#x2019;,&#x201A;</string>
+ <string name="double_quotes">&#x201C;,&#x201D;,&#x201E;</string>
+ <string name="single_angle_quotes">!text/single_laqm_raqm_rtl</string>
+ <string name="double_angle_quotes">!text/double_laqm_raqm_rtl</string>
</resources>
diff --git a/tools/maketext/res/values-ka/donottranslate-more-keys.xml b/tools/maketext/res/values-ka/donottranslate-more-keys.xml
index c516c592e..8c2add44c 100644
--- a/tools/maketext/res/values-ka/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-ka/donottranslate-more-keys.xml
@@ -23,4 +23,6 @@
U+10D1: "ბ" GEORGIAN LETTER BAN
U+10D2: "გ" GEORGIAN LETTER GAN -->
<string name="label_to_alpha_key">&#x10D0;&#x10D1;&#x10D2;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-lt/donottranslate-more-keys.xml b/tools/maketext/res/values-lt/donottranslate-more-keys.xml
index 1491d954e..7e2b8a076 100644
--- a/tools/maketext/res/values-lt/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-lt/donottranslate-more-keys.xml
@@ -104,4 +104,6 @@
<!-- U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE -->
<string name="more_keys_for_g">&#x0123;,&#x011F;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-lv/donottranslate-more-keys.xml b/tools/maketext/res/values-lv/donottranslate-more-keys.xml
index d0a44480a..c64e37bc8 100644
--- a/tools/maketext/res/values-lv/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-lv/donottranslate-more-keys.xml
@@ -103,4 +103,6 @@
<!-- U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE -->
<string name="more_keys_for_g">&#x0123;,&#x011F;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-mk/donottranslate-more-keys.xml b/tools/maketext/res/values-mk/donottranslate-more-keys.xml
index d0fa1e4b6..2db75c8f5 100644
--- a/tools/maketext/res/values-mk/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-mk/donottranslate-more-keys.xml
@@ -35,18 +35,6 @@
U+0411: "Б" CYRILLIC CAPITAL LETTER BE
U+0412: "В" CYRILLIC CAPITAL LETTER VE -->
<string name="label_to_alpha_key">&#x0410;&#x0411;&#x0412;</string>
- <!-- 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,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string> -->
- <string name="more_keys_for_double_quote">!fixedColumnOrder!5,&#x201E;,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;</string>
- <!-- 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string> -->
- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!5,&#x201E;,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-nb/donottranslate-more-keys.xml b/tools/maketext/res/values-nb/donottranslate-more-keys.xml
index 49e6d5faf..2cecb5e65 100644
--- a/tools/maketext/res/values-nb/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-nb/donottranslate-more-keys.xml
@@ -57,4 +57,6 @@
<string name="more_keys_for_nordic_row2_10">&#x00F6;</string>
<!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS -->
<string name="more_keys_for_nordic_row2_11">&#x00E4;</string>
+ <string name="single_quotes">!text/single_9qm_rqm</string>
+ <string name="double_quotes">!text/double_9qm_rqm</string>
</resources>
diff --git a/tools/maketext/res/values-nl/donottranslate-more-keys.xml b/tools/maketext/res/values-nl/donottranslate-more-keys.xml
index 73768aff2..e5d82951a 100644
--- a/tools/maketext/res/values-nl/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-nl/donottranslate-more-keys.xml
@@ -63,4 +63,6 @@
<string name="more_keys_for_n">&#x00F1;,&#x0144;</string>
<!-- U+0133: "ij" LATIN SMALL LIGATURE IJ -->
<string name="more_keys_for_y">&#x0133;</string>
+ <string name="single_quotes">!text/single_9qm_rqm</string>
+ <string name="double_quotes">!text/double_9qm_rqm</string>
</resources>
diff --git a/tools/maketext/res/values-pl/donottranslate-more-keys.xml b/tools/maketext/res/values-pl/donottranslate-more-keys.xml
index 0f8a59bd6..b5cf6a0fa 100644
--- a/tools/maketext/res/values-pl/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-pl/donottranslate-more-keys.xml
@@ -62,4 +62,6 @@
<string name="more_keys_for_z">&#x017C;,&#x017A;,&#x017E;</string>
<!-- U+0142: "ł" LATIN SMALL LETTER L WITH STROKE -->
<string name="more_keys_for_l">&#x0142;</string>
+ <string name="single_quotes">!text/single_9qm_rqm</string>
+ <string name="double_quotes">!text/double_9qm_rqm</string>
</resources>
diff --git a/tools/maketext/res/values-ro/donottranslate-more-keys.xml b/tools/maketext/res/values-ro/donottranslate-more-keys.xml
index 44613cf85..f399eb28e 100644
--- a/tools/maketext/res/values-ro/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-ro/donottranslate-more-keys.xml
@@ -42,4 +42,6 @@
<string name="more_keys_for_s">&#x0219;,&#x00DF;,&#x015B;,&#x0161;</string>
<!-- U+021B: "ț" LATIN SMALL LETTER T WITH COMMA BELOW -->
<string name="more_keys_for_t">&#x021B;</string>
+ <string name="single_quotes">!text/single_9qm_rqm</string>
+ <string name="double_quotes">!text/double_9qm_rqm</string>
</resources>
diff --git a/tools/maketext/res/values-ru/donottranslate-more-keys.xml b/tools/maketext/res/values-ru/donottranslate-more-keys.xml
index bb47fecf5..f62c90ffc 100644
--- a/tools/maketext/res/values-ru/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-ru/donottranslate-more-keys.xml
@@ -37,4 +37,6 @@
U+0411: "Б" CYRILLIC CAPITAL LETTER BE
U+0412: "В" CYRILLIC CAPITAL LETTER VE -->
<string name="label_to_alpha_key">&#x0410;&#x0411;&#x0412;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values-sk/donottranslate-more-keys.xml b/tools/maketext/res/values-sk/donottranslate-more-keys.xml
index f6e1e8d72..2ed538e5b 100644
--- a/tools/maketext/res/values-sk/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-sk/donottranslate-more-keys.xml
@@ -104,4 +104,8 @@
<!-- U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE -->
<string name="more_keys_for_g">&#x0123;,&#x011F;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-sl/donottranslate-more-keys.xml b/tools/maketext/res/values-sl/donottranslate-more-keys.xml
index ccff2ac29..1e5d1d71f 100644
--- a/tools/maketext/res/values-sl/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-sl/donottranslate-more-keys.xml
@@ -27,4 +27,8 @@
<string name="more_keys_for_d">&#x0111;</string>
<!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON -->
<string name="more_keys_for_z">&#x017E;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-sr/donottranslate-more-keys.xml b/tools/maketext/res/values-sr/donottranslate-more-keys.xml
index c41ca95bd..c00d2a665 100644
--- a/tools/maketext/res/values-sr/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-sr/donottranslate-more-keys.xml
@@ -54,18 +54,8 @@
U+0411: "Б" CYRILLIC CAPITAL LETTER BE
U+0412: "В" CYRILLIC CAPITAL LETTER VE -->
<string name="label_to_alpha_key">&#x0410;&#x0411;&#x0412;</string>
- <!-- 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,&#x201E;,&#x201C;,&#x201D;,&#x201F;,&#x00AB;,&#x00BB;</string> -->
- <string name="more_keys_for_double_quote">!fixedColumnOrder!5,&#x201E;,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;</string>
- <!-- 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string> -->
- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!5,&#x201E;,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-sv/donottranslate-more-keys.xml b/tools/maketext/res/values-sv/donottranslate-more-keys.xml
index d479191f4..a36a13eb2 100644
--- a/tools/maketext/res/values-sv/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-sv/donottranslate-more-keys.xml
@@ -51,4 +51,6 @@
<string name="more_keys_for_nordic_row2_10">&#x00F8;</string>
<!-- U+00E6: "æ" LATIN SMALL LETTER AE -->
<string name="more_keys_for_nordic_row2_11">&#x00E6;</string>
+ <string name="single_angle_quotes">!text/single_raqm_laqm</string>
+ <string name="double_angle_quotes">!text/double_raqm_laqm</string>
</resources>
diff --git a/tools/maketext/res/values-uk/donottranslate-more-keys.xml b/tools/maketext/res/values-uk/donottranslate-more-keys.xml
index 09e246b5c..cc05cc697 100644
--- a/tools/maketext/res/values-uk/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-uk/donottranslate-more-keys.xml
@@ -41,4 +41,6 @@
U+0411: "Б" CYRILLIC CAPITAL LETTER BE
U+0412: "В" CYRILLIC CAPITAL LETTER VE -->
<string name="label_to_alpha_key">&#x0410;&#x0411;&#x0412;</string>
+ <string name="single_quotes">!text/single_9qm_lqm</string>
+ <string name="double_quotes">!text/double_9qm_lqm</string>
</resources>
diff --git a/tools/maketext/res/values/donottranslate-more-keys.xml b/tools/maketext/res/values/donottranslate-more-keys.xml
index a5be3489a..c2b7513f3 100644
--- a/tools/maketext/res/values/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values/donottranslate-more-keys.xml
@@ -62,13 +62,10 @@
<string name="more_keys_for_cyrillic_i"></string>
<!-- Label for "switch to alphabetic" key. -->
<string name="label_to_alpha_key">ABC</string>
- <string name="more_keys_for_single_quote">!fixedColumnOrder!4,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
- <!-- 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;</string> -->
- <string name="more_keys_for_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;</string>
- <!-- 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,&#x201C;,&#x201D;,&#x201E;,&#x201F;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string> -->
- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,&#x201C;,&#x201D;,&#x00AB;,&#x00BB;,&#x2018;,&#x2019;,&#x201A;,&#x201B;</string>
+ <string name="single_quotes">!text/single_lqm_rqm</string>
+ <string name="double_quotes">!text/double_lqm_rqm</string>
+ <string name="single_angle_quotes">!text/single_laqm_raqm</string>
+ <string name="double_angle_quotes">!text/double_laqm_raqm</string>
<!-- U+00A2: "¢" CENT SIGN
U+00A3: "£" POUND SIGN
U+20AC: "€" EURO SIGN
@@ -99,16 +96,7 @@
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 -->
+ U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -->
<string name="more_keys_for_less_than">!fixedColumnOrder!3,&#x2039;,&#x2264;,&#x00AB;</string>
<string name="more_keys_for_greater_than">!fixedColumnOrder!3,&#x203A;,&#x2265;,&#x00BB;</string>
<string name="more_keys_for_arabic_diacritics"></string>
@@ -218,4 +206,43 @@
<!-- popular web domains for the locale - most popular, displayed on the keyboard -->
<string name="more_keys_for_popular_domain">"!hasLabels!,.net,.org,.gov,.edu"</string>
<string name="more_keys_for_smiley">"!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ "</string>
+ <!-- U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ 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+201C: "“" LEFT DOUBLE QUOTATION MARK
+ U+201D: "”" RIGHT DOUBLE QUOTATION MARK
+ U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
+ <!-- Abbreviations are:
+ laqm: LEFT-POINTING ANGLE QUOTATION MARK
+ raqm: RIGHT-POINTING ANGLE QUOTATION MARK
+ rtl: Right-To-Left script order
+ lqm: LEFT QUOTATION MARK
+ rqm: RIGHT QUOTATION MARK
+ 9qm: LOW-9 QUOTATION MARK -->
+ <!-- The following each quotation mark pair consist of
+ <opening quotation mark>, <closing quotation mark>
+ and is named after (single|double)_<opening quotation mark>_<closing quotation mark>. -->
+ <string name="single_laqm_raqm">&#x2039;,&#x203A;</string>
+ <string name="single_laqm_raqm_rtl">&#x2039;|&#x203A;,&#x203A;|&#x2039;</string>
+ <string name="single_raqm_laqm">&#x203A;,&#x2039;</string>
+ <string name="double_laqm_raqm">&#x00AB;,&#x00BB;</string>
+ <string name="double_laqm_raqm_rtl">&#x00AB;|&#x00BB;,&#x00BB;|&#x00AB;</string>
+ <string name="double_raqm_laqm">&#x00BB;,&#x00AB;</string>
+ <!-- The following each quotation mark triplet consists of
+ <another quotation mark>, <opening quotation mark>, <closing quotation mark>
+ and is named after (single|double)_<opening quotation mark>_<closing quotation mark>. -->
+ <string name="single_lqm_rqm">&#x201A;,&#x2018;,&#x2019;</string>
+ <string name="single_9qm_lqm">&#x2019;,&#x201A;,&#x2018;</string>
+ <string name="single_9qm_rqm">&#x2018;,&#x201A;,&#x2019;</string>
+ <string name="double_lqm_rqm">&#x201E;,&#x201C;,&#x201D;</string>
+ <string name="double_9qm_lqm">&#x201D;,&#x201E;,&#x201C;</string>
+ <string name="double_9qm_rqm">&#x201C;,&#x201E;,&#x201D;</string>
+ <string name="more_keys_for_single_quote">!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes</string>
+ <string name="more_keys_for_double_quote">!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes</string>
+ <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes</string>
</resources>