aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--java/proguard.flags12
-rw-r--r--java/res/values-af/strings.xml17
-rw-r--r--java/res/values-am/strings.xml17
-rw-r--r--java/res/values-ar/strings.xml17
-rw-r--r--java/res/values-be/strings.xml17
-rw-r--r--java/res/values-bg/strings.xml17
-rw-r--r--java/res/values-ca/strings.xml17
-rw-r--r--java/res/values-cs/strings.xml17
-rw-r--r--java/res/values-da/strings.xml17
-rw-r--r--java/res/values-de/strings.xml17
-rw-r--r--java/res/values-el/strings.xml17
-rw-r--r--java/res/values-en-rGB/strings.xml17
-rw-r--r--java/res/values-es-rUS/strings.xml17
-rw-r--r--java/res/values-es/strings.xml17
-rw-r--r--java/res/values-et/strings.xml17
-rw-r--r--java/res/values-fa/strings.xml17
-rw-r--r--java/res/values-fi/strings.xml17
-rw-r--r--java/res/values-fr/strings.xml17
-rw-r--r--java/res/values-hi/strings.xml17
-rw-r--r--java/res/values-hr/strings.xml17
-rw-r--r--java/res/values-hu/strings.xml17
-rw-r--r--java/res/values-in/strings.xml17
-rw-r--r--java/res/values-it/strings.xml17
-rw-r--r--java/res/values-iw/strings.xml17
-rw-r--r--java/res/values-ja/strings.xml17
-rw-r--r--java/res/values-ko/strings.xml17
-rw-r--r--java/res/values-lt/strings.xml17
-rw-r--r--java/res/values-lv/strings.xml17
-rw-r--r--java/res/values-ms/strings.xml17
-rw-r--r--java/res/values-nb/strings.xml17
-rw-r--r--java/res/values-nl/strings.xml17
-rw-r--r--java/res/values-pl/strings.xml17
-rw-r--r--java/res/values-pt-rPT/strings.xml17
-rw-r--r--java/res/values-pt/strings.xml17
-rw-r--r--java/res/values-rm/strings.xml26
-rw-r--r--java/res/values-ro/strings.xml17
-rw-r--r--java/res/values-ru/strings.xml17
-rw-r--r--java/res/values-sk/strings.xml17
-rw-r--r--java/res/values-sl/strings.xml17
-rw-r--r--java/res/values-sr/strings.xml17
-rw-r--r--java/res/values-sv/strings.xml15
-rw-r--r--java/res/values-sw/strings.xml17
-rw-r--r--java/res/values-th/strings.xml17
-rw-r--r--java/res/values-tl/strings.xml17
-rw-r--r--java/res/values-tr/strings.xml17
-rw-r--r--java/res/values-uk/strings.xml17
-rw-r--r--java/res/values-vi/strings.xml17
-rw-r--r--java/res/values-zh-rCN/strings.xml17
-rw-r--r--java/res/values-zh-rTW/strings.xml17
-rw-r--r--java/res/values-zu/strings.xml17
-rw-r--r--java/res/values/config.xml7
-rw-r--r--java/res/values/strings.xml35
-rw-r--r--java/res/xml/key_styles_common.xml19
-rw-r--r--java/res/xml/key_styles_f1.xml43
-rw-r--r--java/res/xml/prefs.xml24
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java12
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java119
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java7
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java17
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java26
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java30
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java28
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java27
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java8
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java17
-rw-r--r--java/src/com/android/inputmethod/latin/AutoCorrection.java52
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java68
-rw-r--r--java/src/com/android/inputmethod/latin/BoundedTreeSet.java49
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java22
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsDictionary.java178
-rw-r--r--java/src/com/android/inputmethod/latin/Dictionary.java71
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java56
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java11
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtils.java182
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java39
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableDictionary.java98
-rw-r--r--java/src/com/android/inputmethod/latin/InputPointers.java131
-rw-r--r--java/src/com/android/inputmethod/latin/LastComposedWord.java14
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java827
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java2
-rw-r--r--java/src/com/android/inputmethod/latin/NativeUtils.java32
-rw-r--r--java/src/com/android/inputmethod/latin/ResearchLogger.java1400
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java431
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java65
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java96
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java3
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java432
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java33
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java11
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsDictionary.java54
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java10
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java56
-rw-r--r--java/src/com/android/inputmethod/latin/UserBinaryDictionary.java35
-rw-r--r--java/src/com/android/inputmethod/latin/UserDictionary.java225
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictionary.java11
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java16
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java13
-rw-r--r--java/src/com/android/inputmethod/latin/WhitelistDictionary.java2
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java32
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java6
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java103
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java5
103 files changed, 3173 insertions, 2972 deletions
diff --git a/java/proguard.flags b/java/proguard.flags
index 34e23aa9a..ca205b927 100644
--- a/java/proguard.flags
+++ b/java/proguard.flags
@@ -3,10 +3,6 @@
<init>(...);
}
--keep class com.android.inputmethod.latin.Flag {
- *;
-}
-
-keep class com.android.inputmethod.keyboard.ProximityInfo {
<init>(com.android.inputmethod.keyboard.ProximityInfo);
}
@@ -41,13 +37,7 @@
}
-keep class com.android.inputmethod.latin.ResearchLogger {
- void setLogFileManager(...);
- void clearAll();
- com.android.inputmethod.latin.ResearchLogger$LogFileManager getLogFileManager();
-}
-
--keep class com.android.inputmethod.latin.ResearchLogger$LogFileManager {
- java.lang.String getContents();
+ void flush();
}
-keep class com.android.inputmethod.keyboard.KeyboardLayoutSet$Builder {
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index 7431fced8..902edda78 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-sleutelbord (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-sleutelbordinstellings"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropsies"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Navorsing-loglĂȘerbevele"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android-speltoetser"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-speltoetser (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Speltoetser se instellings"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Verstek"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Stel kontakname voor"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gebruik name van kontakte vir voorstelle en korreksies"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Aktiveer herkorrigerings"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Stel voorstelle vir herkorrigerings"</string>
<string name="auto_cap" msgid="1719746674854628252">"Outohoofletters"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Voeg woordeboeke by"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Hoofwoordeboek"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Matig"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressief"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Baie aggressief"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Volgendewoordvoorstelle"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gebruik vorige woord om voorstelle te verbeter"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Volgendewoordvoorspelling"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gebruik vorige woord ook vir voorspelling"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Gestoor"</string>
<string name="label_go_key" msgid="1635148082137219148">"Gaan"</string>
<string name="label_next_key" msgid="362972844525672568">"Volgende"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Steminvoer is gedeaktiveer"</string>
<string name="configure_input_method" msgid="373356270290742459">"Stel invoermetodes op"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Invoertale"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"let op die tydstempel in die loglĂȘer"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Aangetekende tydstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Moenie hierdie sessie aanteken nie"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sessie se loglĂȘer uitgevee"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sessie se loglĂȘer uitgevee"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sessie se loglĂȘer NIE uitgevee nie"</string>
<string name="select_language" msgid="3693815588777926848">"Invoertale"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak weer om te stoor"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Woordeboek beskikbaar"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index d70c05da9..6044d1981 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"ዹAndroid ቁልፍ ሰሌዳ (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ዹAndroid ቁልፍሰሌዳ á‰…áŠ•á‰„áˆźá‰œ"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ግቀቔ áŠ áˆ›áˆ«áŒźá‰œ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ዚጄናቔ ዚምዝግቄ áˆ›áˆ”á‰łá‹ˆáˆ» ቔዕዛዞቜ"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android ዹፊደል ማሚሚያ"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android ዹፊደል ማሚሚያ (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ዹፊደል አራሚ á‰…áŠ•á‰„áˆźá‰œ"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ነባáˆȘ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ዚዕውቂያ ሔም ጠቁም"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ኚዕውቂያዎቜ ለጄቆማዎቜ ኄና ማሔተካኚያዎቜ ሔሞቜ ተጠቀም"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ዔጋሚ ለማሔተካኚል አንቃ"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ዔጋሚ ለማሔተካኚል ጄቆማዎቜን አዘጋጅ"</string>
<string name="auto_cap" msgid="1719746674854628252">"ራሔ-ሰር አቱይ ማዔሚግ"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"መዝገበ ቃላቶቜ ጹምር"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ዋና መዝገበ ቃላቔ"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"መጠነኛ"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"ኃይለኛ"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"በጣም ቁጡ"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"ዹቀጣይ ቃል አሔተያዚቶቜ"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"áˆáŠ­áˆźá‰œáŠ• ለማሻሻል ቀዳሚ ቃል ተጠቀም"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ዹቀጣይ ቃል ግምቔ"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ለቔንበያ ዹቀደመ ቃል ኄንá‹Čሁ ተጠቀም"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ተቀምጧል"</string>
<string name="label_go_key" msgid="1635148082137219148">"ሂዔ"</string>
<string name="label_next_key" msgid="362972844525672568">"በመቀጠል"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"ዚዔምፅ ግቀቔ ቩዝኗል"</string>
<string name="configure_input_method" msgid="373356270290742459">"ግቀቔ ሜተዶቜን አዋቀር"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ቋንቋዎቜ አግቀቔ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ዚምዝግቄ áˆ›áˆ”á‰łá‹ˆáˆ» ጊዜ ማህተም áˆ›áˆ”á‰łá‹ˆáˆ»"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ዹጊዜ ማህተም ተመዝግቧል"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ይህን ክፍለ ጊዜ áŠ„áŠ•á‹łá‰”áˆ˜á‹˜áŒá‰ á‹"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"ዹክፍለጊዜ ምዝግቄ áˆ›áˆ”á‰łá‹ˆáˆ» በመሰሹዝ ላይ"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ዹክፍለ ጊዜ ምዝግቄ áˆ›áˆ”á‰łá‹ˆáˆ» ተሰርዟል"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"ዹክፍለጊዜ ምዝግቄ áˆ›áˆ”á‰łá‹ˆáˆ» አልተሰሹዘም"</string>
<string name="select_language" msgid="3693815588777926848">"ቋንቋዎቜ አግቀቔ"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ለማሔቀመጄ ኄንደገና ንካ"</string>
<string name="has_dictionary" msgid="6071847973466625007">"መዝገበ ቃላቔ አለ"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 5678c40c8..5215f9da1 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Ù„ÙˆŰ­Ű© Ù…ÙŰ§ŰȘÙŠŰ­ Android ‏(AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Ű„ŰčۯۧۯۧŰȘ Ù„ÙˆŰ­Ű© Ù…ÙŰ§ŰȘÙŠŰ­ Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ŰźÙŠŰ§Ű±Ű§ŰȘ Ű§Ù„Ű„Ű±ŰłŰ§Ù„"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ŰŁÙˆŰ§Ù…Ű± ŰłŰŹÙ„Ű§ŰȘ Ű§Ù„ŰšŰ­Ű«"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Ű§Ù„ŰȘŰŻÙ‚ÙŠÙ‚ Ű§Ù„Ű„Ù…Ù„Ű§ŰŠÙŠ في Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Ű§Ù„ŰȘŰŻÙ‚ÙŠÙ‚ Ű§Ù„Ű„Ù…Ù„Ű§ŰŠÙŠ في Android‏ (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Ű„ŰčۯۧۯۧŰȘ Ű§Ù„ŰȘŰŻÙ‚ÙŠÙ‚ Ű§Ù„Ű„Ù…Ù„Ű§ŰŠÙŠ"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Ű§ÙŰȘŰ±Ű§Ű¶ÙŠ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Ű§Ù‚ŰȘ۱ۭۧ ŰŁŰłÙ…Ű§ŰĄ ŰŹÙ‡Ű§ŰȘ Ű§Ù„Ű§ŰȘŰ”Ű§Ù„"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ۧ۳ŰȘŰźŰŻŰ§Ù… Ű§Ù„ŰŁŰłÙ…Ű§ŰĄ من ŰŹÙ‡Ű§ŰȘ Ű§Ù„Ű§ŰȘŰ”Ű§Ù„ Ù„Ù„Ű§Ù‚ŰȘ۱ۭۧۧŰȘ ÙˆŰ§Ù„ŰȘŰ”Ű­ÙŠŰ­Ű§ŰȘ"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ŰȘمكين ŰčÙ…Ù„ÙŠŰ§ŰȘ Ű„Űčۧۯ۩ Ű§Ù„ŰȘŰ”Ű­ÙŠŰ­"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ŰȘŰčيين Ű§Ù‚ŰȘ۱ۭۧۧŰȘ لŰčÙ…Ù„ÙŠŰ§ŰȘ Ű„Űčۧۯ۩ Ű§Ù„ŰȘŰ”Ű­ÙŠŰ­"</string>
<string name="auto_cap" msgid="1719746674854628252">"ŰŁŰ­Ű±Ù ÙƒŰšÙŠŰ±Ű© ŰȘÙ„Ù‚Ű§ŰŠÙŠÙ‹Ű§"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Ű§Ù„Ù‚ÙˆŰ§Ù…ÙŠŰł Ű§Ù„Ű„Ű¶Ű§ÙÙŠŰ©"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Ű§Ù„Ù‚Ű§Ù…ÙˆŰł Ű§Ù„Ű±ŰŠÙŠŰłÙŠ"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"مŰčŰȘŰŻÙ„"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"ۭۧۯ"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"ŰŽŰŻÙŠŰŻ Ű§Ù„Ű”Ű±Ű§Ù…Ű©"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Ű§Ù‚ŰȘ۱ۭۧۧŰȘ Ű§Ù„ÙƒÙ„Ù…Ű§ŰȘ Ű§Ù„ŰȘŰ§Ù„ÙŠŰ©"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ۧ۳ŰȘŰźŰŻŰ§Ù… Ű§Ù„ÙƒÙ„Ù…Ű© Ű§Ù„ŰłŰ§ŰšÙ‚Ű© لŰȘŰ­ŰłÙŠÙ† Ű§Ù„Ű§Ù‚ŰȘ۱ۭۧۧŰȘ"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ŰȘÙ†ŰšŰ€ Ű§Ù„ÙƒÙ„Ù…Ű§ŰȘ Ű§Ù„ŰȘŰ§Ù„ÙŠŰ©"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ۧ۳ŰȘŰźŰŻŰ§Ù… Ű§Ù„ÙƒÙ„Ù…Ű© Ű§Ù„ŰłŰ§ŰšÙ‚Ű© ŰŁÙŠŰ¶Ù‹Ű§ للŰȘÙ†ŰšŰ€"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ŰȘم Ű§Ù„Ű­ÙŰž"</string>
<string name="label_go_key" msgid="1635148082137219148">"ŰȘÙ†ÙÙŠŰ°"</string>
<string name="label_next_key" msgid="362972844525672568">"Ű§Ù„ŰȘŰ§Ù„ÙŠ"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Ű§Ù„Ű„ŰŻŰźŰ§Ù„ Ű§Ù„Ű”ÙˆŰȘي مُŰčŰ·Ù„"</string>
<string name="configure_input_method" msgid="373356270290742459">"ŰȘÙ‡ÙŠŰŠŰ© Ű·Ű±Ù‚ Ű§Ù„Ű„ŰŻŰźŰ§Ù„"</string>
<string name="language_selection_title" msgid="1651299598555326750">"لŰșۧŰȘ Ű§Ù„Ű„ŰŻŰźŰ§Ù„"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Ù…Ù„Ű§Ű­ŰžŰ© ۷ۧۚŰč ŰČمني في ŰłŰŹÙ„"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ŰȘم ŰȘŰłŰŹÙŠÙ„ Ű§Ù„Ű·Ű§ŰšŰč Ű§Ù„ŰČمني"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ŰčŰŻÙ… ŰȘŰłŰŹÙŠÙ„ Ù‡Ű°Ù‡ Ű§Ù„ŰŹÙ„ŰłŰ©"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"ŰŹŰ§Ű±Ù Ű­Ű°Ù ŰłŰŹÙ„ Ű§Ù„ŰŹÙ„ŰłŰ©"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ŰȘم Ű­Ű°Ù ŰłŰŹÙ„ Ű§Ù„ŰŹÙ„ŰłŰ©"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"لم يŰȘم Ű­Ű°Ù ŰłŰŹÙ„ Ű§Ù„ŰŹÙ„ŰłŰ©"</string>
<string name="select_language" msgid="3693815588777926848">"لŰșۧŰȘ Ű§Ù„Ű„ŰŻŰźŰ§Ù„"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Ű§Ù„Ù…Űł Ù…Ű±Ű© ŰŁŰźŰ±Ù‰ Ù„Ù„Ű­ÙŰž"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ű§Ù„Ù‚Ű§Ù…ÙˆŰł مŰȘۭۧ"</string>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index 4d14565b9..4d3085086 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"КлаĐČіятура Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ĐĐ°Đ»Đ°ĐŽŃ‹ ĐșлаĐČіятуры Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ĐŸĐ°Ń€Đ°ĐŒĐ”Ń‚Ń€Ń‹ ўĐČĐŸĐŽŃƒ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ĐšĐ°ĐŒĐ°ĐœĐŽŃ‹ ĐłiŃŃ‚ĐŸŃ€Ń‹Ń ЎаслДЎаĐČĐ°ĐœĐœŃŃž"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"IĐœŃŃ‚Ń€ŃƒĐŒĐ”ĐœŃ‚ праĐČДрĐși праĐČапiсу ĐŽĐ»Ń Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"IĐœŃŃ‚Ń€ŃƒĐŒĐ”ĐœŃ‚ праĐČДрĐși праĐČапiсу ĐŽĐ»Ń Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ĐĐ°Đ»Đ°ĐŽŃ‹ праĐČДрĐșі арфаграфіі"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Па Đ·ĐŒĐ°ŃžŃ‡Đ°ĐœĐœŃ–"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ĐŸŃ€Đ°ĐżĐ°Đœ. Ń–ĐŒŃ‘ĐœŃ‹ ĐșĐ°ĐœŃ‚Đ°Đșтаў"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ВыĐșĐ°Ń€Ń‹ŃŃ‚ĐŸŃžĐČаць Ń–ĐŒŃ‘ĐœŃ‹ са спісу ĐșĐ°ĐœŃ‚Đ°Đșтаў ĐŽĐ»Ń ĐżŃ€Đ°ĐżĐ°ĐœĐŸŃž і ĐČыпраўл."</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ĐŁĐșĐ»ŃŽŃ‡Ń‹Ń†ŃŒ ĐșарэĐșцiŃ€ĐŸŃžĐșі"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ЗаЮаць ĐżŃ€Đ°ĐżĐ°ĐœĐŸĐČы ĐŽĐ»Ń ĐșарэĐșцiŃ€ĐŸŃžĐșі"</string>
<string name="auto_cap" msgid="1719746674854628252">"ĐŃžŃ‚Đ°ĐŒĐ°Ń‚Ń‹Ń‡ĐœĐ° Ń€Đ°Đ±Ń–Ń†ŃŒ ĐČŃĐ»Ń–Đșія літары"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ДаЮатĐșĐŸĐČыя ŃĐ»ĐŸŃžĐœŃ–Đșі"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ĐŃĐœĐŸŃžĐœŃ‹ ŃĐ»ĐŸŃžĐœŃ–Đș"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Хціплы"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"ĐĐłŃ€ŃŃŃ–ŃžĐœŃ‹"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Đ’Đ”Đ»ŃŒĐŒŃ– Đ°ĐłŃ€ŃŃŃ–ŃžĐœŃ‹"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"ПаЮĐșазĐși ĐŽĐ»Ń ĐœĐ°ŃŃ‚ŃƒĐżĐœĐ°ĐłĐ° ŃĐ»ĐŸĐČа"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ВыĐșарыстаць ĐżĐ°ĐżŃŃ€ŃĐŽĐœŃĐ” ŃĐ»ĐŸĐČа, Đșаб ĐżĐ°Đ»Đ”ĐżŃˆŃ‹Ń†ŃŒ ĐżŃ€Đ°ĐżĐ°ĐœĐŸĐČы"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ПаЮĐșазĐșа ĐœĐ°ŃŃ‚ŃƒĐżĐœĐ°ĐłĐ° ŃĐ»ĐŸĐČа"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ВыĐșĐ°Ń€Ń‹ŃŃ‚Đ°ĐœĐœĐ” ĐżĐ°ĐżŃŃ€ŃĐŽĐœŃĐłĐ° ŃĐ»ĐŸĐČа ĐŽĐ»Ń паЎĐșазаĐș"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ЗахаĐČĐ°ĐœŃ‹Ń"</string>
<string name="label_go_key" msgid="1635148082137219148">"Пачаць"</string>
<string name="label_next_key" msgid="362972844525672568">"ДалДĐč"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"ГаласаĐČы ĐœĐ°Đ±ĐŸŃ€ аЎĐșĐ»."</string>
<string name="configure_input_method" msgid="373356270290742459">"ĐĐ°Đ»Đ°ĐŽĐ° ĐŒĐ”Ń‚Đ°ĐŽĐ°Ńž уĐČĐŸĐŽŃƒ"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ĐœĐŸĐČы ўĐČĐŸĐŽŃƒ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ĐŸĐ°Đ·ĐœĐ°Ń‡Ń‹Ń†ŃŒ час у ĐłiŃŃ‚ĐŸŃ€Ń‹i"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ЗапiŃĐ°ĐœŃ‹Ń ĐżĐ°Đ·ĐœĐ°Đșі"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ĐĐ” рэгістраĐČаць гэты ŃĐ”Đ°ĐœŃ"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Đ’Ń‹ĐŽĐ°Đ»Đ”ĐœĐœĐ” ĐłiŃŃ‚ĐŸŃ€Ń‹i ŃĐ”Đ°ĐœŃĐ°"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ГiŃŃ‚ĐŸŃ€Ń‹Ń ŃĐ”Đ°ĐœŃĐ° ĐČŃ‹ĐŽĐ°Đ»Đ”ĐœĐ°"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"ГiŃŃ‚ĐŸŃ€Ń‹Ń ŃĐ”Đ°ĐœŃĐ° НЕ ĐČŃ‹ĐŽĐ°Đ»Đ”ĐœĐ°"</string>
<string name="select_language" msgid="3693815588777926848">"ĐœĐŸĐČы ўĐČĐŸĐŽŃƒ"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ДаĐșŃ€Đ°ĐœŃ–Ń†Đ”ŃŃ Đ·ĐœĐŸŃž, Đșаб захаĐČаць"</string>
<string name="has_dictionary" msgid="6071847973466625007">"ĐĄĐ»ĐŸŃžĐœŃ–Đș ĐŽĐ°ŃŃ‚ŃƒĐżĐœŃ‹"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index 106a91806..dad1f3825 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"КлаĐČоатура ĐœĐ° Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ĐĐ°ŃŃ‚Ń€ĐŸĐčĐșĐž ĐœĐ° ĐșлаĐČоатурата ĐœĐ° Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Опцоо за ĐČъĐČĐ”Đ¶ĐŽĐ°ĐœĐ”"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ĐšĐŸĐŒĐ°ĐœĐŽĐž за рДг. фаĐčĐ» за ĐżŃ€ĐŸŃƒŃ‡ĐČĐ°ĐœĐžŃ"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"ĐŸŃ€ĐŸĐłŃ€Đ°ĐŒĐ° за праĐČĐŸĐżĐžŃĐœĐ° ĐżŃ€ĐŸĐČДрĐșа за Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"ĐŸŃ€ĐŸĐłŃ€Đ°ĐŒĐ° за праĐČĐŸĐżĐžŃĐœĐ° ĐżŃ€ĐŸĐČДрĐșа за Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ĐĐ°ŃŃ‚Ń€ĐŸĐčĐșĐž за ĐżŃ€ĐŸĐČДрĐșа ĐœĐ° праĐČĐŸĐżĐžŃĐ°"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ĐŸĐŸ ĐżĐŸĐŽŃ€Đ°Đ·Đ±ĐžŃ€Đ°ĐœĐ”"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ĐŸŃ€Đ”ĐŽĐ»ĐŸĐ¶Đ”ĐœĐžŃ за ĐșĐŸĐœŃ‚Đ°Đșто"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Đ˜Đ·ĐżĐŸĐ»Đ·ĐČĐ°ĐœĐ” ĐœĐ° ĐžĐŒĐ”ĐœĐ° ĐŸŃ‚ â€žĐšĐŸĐœŃ‚Đ°Đșто“ за ĐżŃ€Đ”ĐŽĐ»ĐŸĐ¶Đ”ĐœĐžŃ Đž ĐżĐŸĐżŃ€Đ°ĐČĐșĐž"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ĐŸĐŸĐČŃ‚ĐŸŃ€ĐœĐž ĐżĐŸĐżŃ€Đ°ĐČĐșĐž: АĐșтоĐČ."</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ЗаЮаĐČĐ°ĐœĐ” ĐœĐ° ĐżŃ€Đ”ĐŽĐ»ĐŸĐ¶Đ”ĐœĐžŃ за ĐżĐŸĐČŃ‚ĐŸŃ€ĐœĐž ĐżĐŸĐżŃ€Đ°ĐČĐșĐž"</string>
<string name="auto_cap" msgid="1719746674854628252">"АĐČŃ‚ĐŸĐŒĐ°Ń‚ĐžŃ‡ĐœĐŸ ĐżĐŸŃŃ‚Đ°ĐČŃĐœĐ” ĐœĐ° глаĐČĐœĐž буĐșĐČĐž"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Đ”ĐŸĐ±Đ°ĐČĐ”ĐœĐž Ń€Đ”Ń‡ĐœĐžŃ†Đž"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ĐžŃĐœĐŸĐČĐ”Đœ Ń€Đ”Ń‡ĐœĐžĐș"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ĐŁĐŒĐ”Ń€Đ”ĐœĐŸ"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"АгрДсОĐČĐœĐŸ"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"ĐœĐœĐŸĐłĐŸ агрДсОĐČĐœĐŸ"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"ĐŸŃ€Đ”ĐŽĐ»ĐŸĐ¶Đ”ĐœĐžŃ за слДЎĐČащата ĐŽŃƒĐŒĐ°"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Đ˜Đ·ĐżĐŸĐ»Đ·ĐČĐ°ĐœĐ” ĐœĐ° ĐżŃ€Đ”ĐŽĐžŃˆĐœĐ°Ń‚Đ° ĐŽŃƒĐŒĐ° за ĐżĐŸĐŽĐŸĐ±Ń€ŃĐČĐ°ĐœĐ” ĐœĐ° ĐżŃ€Đ”ĐŽĐ»ĐŸĐ¶Đ”ĐœĐžŃŃ‚Đ°"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ĐŸŃ€Đ”ĐŽĐČĐžĐ¶ĐŽĐ°ĐœĐ” ĐœĐ° слДЎĐČащата ĐŽŃƒĐŒĐ°"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Đ˜Đ·ĐżĐŸĐ»Đ·ĐČĐ°ĐœĐ” ĐœĐ° ĐżŃ€Đ”ĐŽĐžŃˆĐœĐ°Ń‚Đ° ĐŽŃƒĐŒĐ° Đž за прДЎĐČĐžĐ¶ĐŽĐ°ĐœĐ”"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Đ—Đ°ĐżĐ°Đ·Đ”ĐœĐŸ"</string>
<string name="label_go_key" msgid="1635148082137219148">"Старт"</string>
<string name="label_next_key" msgid="362972844525672568">"ĐĐ°ĐżŃ€Đ”ĐŽ"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Глас. ĐČъĐČДжЎ. Đ” ЎДаĐșт."</string>
<string name="configure_input_method" msgid="373356270290742459">"ĐšĐŸĐœŃ„ĐžĐłŃƒŃ€ĐžŃ€Đ°ĐœĐ” ĐœĐ° ĐČъĐČĐ”Đ¶ĐŽĐ°ĐœĐ”Ń‚ĐŸ"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Đ’Ń…ĐŸĐŽĐœĐž ДзОцО"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ĐžŃ‚Đ±Đ”Đ»ŃĐ·ĐČĐ°ĐœĐ” ĐœĐ° часа ĐČ Ń€Đ”Đł. фаĐčĐ»"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Часът Đ” Đ·Đ°ĐżĐžŃĐ°Đœ"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"БДз рДгОстр. ĐœĐ° ŃĐ”ŃĐžŃŃ‚Đ°"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"РДг. фаĐčĐ» ĐœĐ° ŃĐ”ŃĐžŃŃ‚Đ° сД ОзтрОĐČа"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"РДг. фаĐčĐ» ĐœĐ° ŃĐ”ŃĐžŃŃ‚Đ° Đ” ОзтрОт"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"РДг. фаĐčĐ» ĐœĐ° ŃĐ”ŃĐžŃŃ‚Đ° НЕ Е ОзтрОт"</string>
<string name="select_language" msgid="3693815588777926848">"ЕзОцО за ĐČъĐČĐ”Đ¶ĐŽĐ°ĐœĐ”"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Đ”ĐŸĐșĐŸŃĐœĐ”Ń‚Đ” ĐŸŃ‚ĐœĐŸĐČĐŸ, за Ўа запазОтД"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Đ˜ĐŒĐ° ĐŽĐŸŃŃ‚ŃŠĐż ĐŽĐŸ Ń€Đ”Ń‡ĐœĐžĐș"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index e3adbcff4..1341c4829 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclat d\'Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ConfiguraciĂł del teclat d\'Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcions d\'entrada"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Recerca d\'ordres de reg."</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortogrĂ fic d\'Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortogrĂ fic d\'Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ConfiguraciĂł de la correcciĂł ortogrĂ fica"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminat"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggereix noms contactes"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilitza els noms de Contactes per a suggeriments i correccions"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Activa la capacitat de tornar a corregir"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Estableix suggeriments per tornar a corregir"</string>
<string name="auto_cap" msgid="1719746674854628252">"MajĂșscules automĂ tiques"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionaris complementaris"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Diccionari principal"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderada"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Molt agressiu"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Suggeriments de paraula segĂŒent"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilitza la paraula anterior per millorar els suggeriments"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"PredicciĂł de paraula segĂŒent"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilitza també la paraula anterior per a la predicció"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: desada"</string>
<string name="label_go_key" msgid="1635148082137219148">"Vés"</string>
<string name="label_next_key" msgid="362972844525672568">"SegĂŒent"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. veu desactiv."</string>
<string name="configure_input_method" msgid="373356270290742459">"Configura mĂštodes d\'entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomes d\'entrada"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Indica m. horĂ ria al reg."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marca horĂ ria enregistrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"No enregistris la sessiĂł"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Suprimint registre de ses."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registre de ses. suprimit"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Registre de ses. NO sup."</string>
<string name="select_language" msgid="3693815588777926848">"Idiomes d\'entrada"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Torna a tocar per desar"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Diccionari disponible"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 90d840cd8..2e62ffec6 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"KlĂĄvesnice Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"NastavenĂ­ klĂĄvesnice Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"MoĆŸnosti zadĂĄvĂĄnĂ­ textu a dat"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Pƙíkazy vĂœvoj. protokolu"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Kontrola pravopisu Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"NastavenĂ­ kontroly pravopisu"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"VĂœchozĂ­"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Navrhovat jména kontaktƯ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"PouĆŸĂ­t jmĂ©na ze seznamu kontaktĆŻ k nĂĄvrhĆŻm a opravĂĄm"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Povolit opětovnĂ© opravy"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastavit nĂĄvrhy pro opětovnĂ© opravy"</string>
<string name="auto_cap" msgid="1719746674854628252">"VelkĂĄ pĂ­smena automaticky"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Doplƈkové slovníky"</string>
<string name="main_dictionary" msgid="4798763781818361168">"HlavnĂ­ slovnĂ­k"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mírné"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"AgresivnĂ­"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Velmi agresivnĂ­"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"NĂĄvrh dalĆĄĂ­ho slova"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"PouĆŸĂ­t pƙedchozĂ­ slovo ke zlepĆĄenĂ­ nĂĄvrhĆŻ"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Odhad dalĆĄĂ­ho slova"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"PouĆŸĂ­t pƙedchozĂ­ slovo takĂ© pro odhad"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: UloĆŸeno"</string>
<string name="label_go_key" msgid="1635148082137219148">"Pƙejít"</string>
<string name="label_next_key" msgid="362972844525672568">"DalĆĄĂ­"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"HlasovĂœ vstup vypnut"</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfigurace metod zadĂĄvĂĄnĂ­"</string>
<string name="language_selection_title" msgid="1651299598555326750">"VstupnĂ­ jazyky"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"UloĆŸit čas do protokolu"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ČasovĂ© razĂ­tko vloĆŸeno"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Neprotokolovat relaci"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"MazĂĄnĂ­ protokolu relace"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Protokol relace smazĂĄn"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Protokol relace nesmazĂĄn"</string>
<string name="select_language" msgid="3693815588777926848">"VstupnĂ­ jazyky"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"OpětovnĂœm dotykem provedete uloĆŸenĂ­"</string>
<string name="has_dictionary" msgid="6071847973466625007">"SlovnĂ­k k dispozici"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 50b0b0a9f..0081c9af5 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-tastatur-indstillinger"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Indstillinger for input"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Forskningslogkommandoer"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android-stavekontrol"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontrol (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Indstillinger for stavekontrol"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ForeslÄ navne pÄ kontakter"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Brug navne fra Kontaktpersoner til forslag og rettelser"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Aktivér fornyet rettelse"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Angiv forslag til fornyet rettelse"</string>
<string name="auto_cap" msgid="1719746674854628252">"Skriv aut. med stort"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"TillĂŠgsordbĂžger"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Hovedordbog"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderat"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressiv"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Meget aggressiv"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Forslag til nĂŠste ord"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Brug forrige ord til at forbedre forslag"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Forudsigelse af nĂŠste ord"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Brug ogsÄ tidligere ord til forudsigelse"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Gemt"</string>
<string name="label_go_key" msgid="1635148082137219148">"GĂ„"</string>
<string name="label_next_key" msgid="362972844525672568">"NĂŠste"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Stemmeinput deaktiveret"</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfigurer inputmetoder"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Inputsprog"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Notér tidsstempel i log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Noteret tidsstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"LogfĂžr ikke denne session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sletter sessionslogfil"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sessionslogfil slettet"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sessionslog IKKE slettet"</string>
<string name="select_language" msgid="3693815588777926848">"Inputsprog"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgĂŠngelig"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 216aac5d9..823f84fba 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-Tastatur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-Tastatureinstellungen"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Eingabeoptionen"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Forschungsprotokollbefehle"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android-RechtschreibprĂŒfung"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-RechtschreibprĂŒfung (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Einstellungen fĂŒr RechtschreibprĂŒfung"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Kontakte vorschlagen"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen aus \"Kontakte\" als VorschlÀge und Korrekturmöglichkeiten anzeigen"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Korrekturen aktivieren"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"VorschlĂ€ge fĂŒr Korrekturen festlegen"</string>
<string name="auto_cap" msgid="1719746674854628252">"Autom. Groß-/Kleinschr."</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Erweiterte WörterbĂŒcher"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Allgemeines Wörterbuch"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"MĂ€ĂŸig"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Stark"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sehr stark"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"VorschlĂ€ge fĂŒr nĂ€chstes Wort"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Zur Verbesserung von VorschlÀgen vorheriges Wort verwenden"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"VervollstĂ€ndigung fĂŒr nĂ€chstes Wort"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Vorheriges Wort auch fĂŒr VervollstĂ€ndigung verwenden"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: gespeichert"</string>
<string name="label_go_key" msgid="1635148082137219148">"Los"</string>
<string name="label_next_key" msgid="362972844525672568">"Weiter"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spracheingabe deaktiviert"</string>
<string name="configure_input_method" msgid="373356270290742459">"Eingabemethoden konfigurieren"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Eingabesprachen"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Zeitstempel im Protokoll"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Zeitstempel aufgenommen"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nicht protokollieren"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Protokoll wird gelöscht..."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Protokoll gelöscht"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Protokoll NICHT gelöscht"</string>
<string name="select_language" msgid="3693815588777926848">"Eingabesprachen"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Zum Speichern erneut berĂŒhren"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfĂŒgbar"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 486346a09..6a7942cd0 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"ΠληÎșÏ„ÏÎżÎ»ÏŒÎłÎčÎż Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ÎĄÏ…ÎžÎŒÎŻÏƒÎ”Îčς πληÎșÏ„ÏÎżÎ»ÎżÎłÎŻÎżÏ… Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ΕπÎčÎ»ÎżÎłÎ­Ï‚ ΔÎčÏƒÏŒÎŽÎżÏ…"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ΈρΔυΜα Î”ÎœÏ„ÎżÎ»ÏŽÎœ ÎșÎ±Ï„Î±ÎłÏÎ±Ï†ÎźÏ‚"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"ÎŸÏÎžÎżÎłÏÎ±Ï†ÎčÎșός Î­Î»Î”ÎłÏ‡ÎżÏ‚ Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"ÎŸÏÎžÎżÎłÏÎ±Ï†ÎčÎșός Î­Î»Î”ÎłÏ‡ÎżÏ‚ Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ÎĄÏ…ÎžÎŒÎŻÏƒÎ”Îčς ÎżÏÎžÎżÎłÏÎ±Ï†ÎčÎșÎżÏ Î”Î»Î­ÎłÏ‡ÎżÏ…"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Î ÏÎżÎ”Ï€ÎčλογΟ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Πρόταση ÎżÎœÎżÎŒÎŹÏ„Ï‰Îœ ΔπαφώΜ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ΧρησÎčÎŒÎżÏ€ÎżÎčÎźÏƒÏ„Î” ÎżÎœÏŒÎŒÎ±Ï„Î± από τÎčς Επαφές ÎłÎčα Ï€ÏÎżÏ„ÎŹÏƒÎ”Îčς ÎșαÎč ÎŽÎčÎżÏÎž."</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Î•ÎœÎ”ÏÎł. Î”Ï€Î±ÎœÎŹÎ». ÎŽÎčÎżÏÎžÏŽÏƒÎ”Ï‰Îœ"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ΟρÎčσΌός Ï€ÏÎżÏ„ÎŹÏƒÎ”Ï‰Îœ ÎłÎčα Î”Ï€Î±ÎœÎ±Î»ÎźÏˆÎ”Îčς ÎŽÎčÎżÏÎžÏŽÏƒÎ”Ï‰Îœ"</string>
<string name="auto_cap" msgid="1719746674854628252">"ΑυτόΌατη Ï‡ÏÎźÏƒÎ· ÎșÎ”Ï†Î±Î»Î±ÎŻÏ‰Îœ"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ΠρόσΞΔτα λΔΟÎčÎșÎŹ"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ΚύρÎčÎż λΔΟÎčÎșό"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ΜέτρÎčα"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Î„ÏˆÎ·Î»Îź"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Î ÎżÎ»Ï ΔπÎčΞΔτÎčÎșÎź"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Î ÏÎżÏ„ÎŹÏƒÎ”Îčς ΔπόΌΔΜωΜ λέΟΔωΜ"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Î§ÏÎźÏƒÎ· Ï€ÏÎżÎ·ÎłÎżÏÎŒÎ”ÎœÎ·Ï‚ λέΟης ÎłÎčα τη ÎČÎ”Î»Ï„ÎŻÏ‰ÏƒÎ· Ï€ÏÎżÏ„ÎŹÏƒÎ”Ï‰Îœ"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ΠρόÎČλΔψη ΔπόΌΔΜης λέΟης"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ΧρησÎčÎŒÎżÏ€ÎżÎčÎźÏƒÏ„Î”, Î”Ï€ÎŻÏƒÎ·Ï‚, τηΜ Ï€ÏÎżÎ·ÎłÎżÏÎŒÎ”ÎœÎ· λέΟη ÎłÎčα πρόÎČλΔψη"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Î‘Ï€ÎżÎžÎ·ÎșΔύτηÎșΔ"</string>
<string name="label_go_key" msgid="1635148082137219148">"ΜΔτ."</string>
<string name="label_next_key" msgid="362972844525672568">"Î•Ï€ÏŒÎŒÎ”ÎœÎż"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"ΑπΔΜ. φωΜητ. Î”ÎŻÏƒÎżÎŽÎżÏ‚"</string>
<string name="configure_input_method" msgid="373356270290742459">"ΔÎčαΌόρφωση ΌΔΞόΎωΜ ΔÎčÏƒÎ±ÎłÏ‰ÎłÎźÏ‚"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ΓλώσσΔς ΔÎčÏƒÏŒÎŽÎżÏ…"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Î§ÏÏŒÎœÎżÏ‚ ÏƒÏ„Îż Î±ÏÏ‡Î”ÎŻÎż ÎșÎ±Ï„Î±ÎłÏ."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ÎšÎ±Ï„Î±ÎłÎ”ÎłÏÎ±ÎŒÎŒÎ­ÎœÎżÏ‚ Ï‡ÏÏŒÎœÎżÏ‚"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Î§Ï‰ÏÎŻÏ‚ Î±ÏÏ‡Î”ÎŻÎż ÎșÎ±Ï„Î±ÎłÏÎ±Ï†ÎźÏ‚"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"ΔÎčÎ±ÎłÏÎ±Ï†Îź Î±ÏÏ‡Î”ÎŻÎżÏ… σύΜΎΔσης"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Î‘ÏÏ‡Î”ÎŻÎż ÎșÎ±Ï„Î±ÎłÏ. ÎŽÎčÎ±ÎłÏÎŹÏ†Î·ÎșΔ"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Î‘ÏÏ‡Î”ÎŻÎż ÎșÎ±Ï„Î±ÎłÏ. ΔΕΝ ÎŽÎčÎ±ÎłÏ."</string>
<string name="select_language" msgid="3693815588777926848">"ΓλώσσΔς ΔÎčÏƒÏŒÎŽÎżÏ…"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Î‘ÎłÎłÎŻÎŸÏ„Î” ÎŸÎ±ÎœÎŹ ÎłÎčα Î±Ï€ÎżÎžÎźÎșΔυση"</string>
<string name="has_dictionary" msgid="6071847973466625007">"ΛΔΟÎčÎșό ÎŽÎčαΞέσÎčÎŒÎż"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 502007666..6ddcbc376 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android keyboard settings"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android spell checker"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android spell checker (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Spellchecking settings"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggest Contact names"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Use names from Contacts for suggestions and corrections"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Enable recorrections"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Set suggestions for recorrections"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-capitalisation"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Add-on dictionaries"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Main dictionary"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressive"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Very aggressive"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Next word suggestions"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Use previous word to improve suggestion"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Next word prediction"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Use previous word also for prediction"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Saved"</string>
<string name="label_go_key" msgid="1635148082137219148">"Go"</string>
<string name="label_next_key" msgid="362972844525672568">"Next"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Voice input is disabled"</string>
<string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Note timestamp in log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Recorded timestamp"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Do not log this session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Deleting session log"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Session log deleted"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Session log NOT deleted"</string>
<string name="select_language" msgid="3693815588777926848">"Input languages"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 34ad0a420..65c4eed61 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado de Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ConfiguraciĂłn de teclado de Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opciones de entrada"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro invest."</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortogrĂĄfico de Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortogrĂĄfico de Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ConfiguraciĂłn del corrector ortogrĂĄfico"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminada"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nombres de contacto"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nombres de los contactos para sugerencias y correcciones"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Activar correcciones"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para realizar correcciones"</string>
<string name="auto_cap" msgid="1719746674854628252">"MayĂșsculas automĂĄticas"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresivo"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerencias para la palabra siguiente"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar la palabra anterior para mejorar las sugerencias"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"PredicciĂłn de la palabra siguiente"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Usar la palabra anterior también para predicción."</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
<string name="label_next_key" msgid="362972844525672568">"Siguiente"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"La entrada por voz estĂĄ inhabilitada"</string>
<string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Marcar tiempo en registro"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marca tiempo registrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"No registrar esta sesiĂłn"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Eliminando registro"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registro sesiĂłn eliminado"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"NO se eliminĂł el registro"</string>
<string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Vuelve a tocar para guardar."</string>
<string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 3c60aa6e2..f3e139950 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Ajustes del teclado de Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opciones entrada texto"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos registro investigaciĂłn"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector de Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector de Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Ajustes del corrector ortogrĂĄfico"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir contactos"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nombres de contactos para sugerencias y correcciones"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Activar nuevas correcciones"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para nuevas correcciones"</string>
<string name="auto_cap" msgid="1719746674854628252">"MayĂșsculas automĂĄticas"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Parcial"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muy agresiva"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Sugerir siguiente palabra"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palabra anterior para mejorar las sugerencias"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Predecir siguiente palabra"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilizar también la palabra anterior para realizar la predicción"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
<string name="label_next_key" msgid="362972844525672568">"Sig."</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entrada de voz inhabilitada"</string>
<string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Anotar marca tiempo en registro"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marca de tiempo registrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"No registrar esta sesiĂłn"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Eliminando registro..."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registro eliminado"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Registro no eliminado"</string>
<string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca otra vez para guardar."</string>
<string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string>
diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml
index 4a592c36b..d89806bb0 100644
--- a/java/res/values-et/strings.xml
+++ b/java/res/values-et/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-klaviatuur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Androidi klaviatuuriseaded"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Sisestusvalikud"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Uuringulogi kÀsud"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Androidi Ôigekirjakontroll"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidi Ôigekirjakontroll (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Õigekirjakontrolli seaded"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Vaikeseade"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Soovita kontaktkirjeid"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Kasuta soovitusteks ja parandusteks nimesid kontaktiloendist"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Uute paranduste lubamine"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Soovituste seadmine uute paranduste jaoks"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automaatne suurtÀhtede kasutamine"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"PistiksÔnaraamatud"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Peamine sÔnaraamat"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"MÔÔdukas"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressiivne"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"VĂ€ga agressiivne"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"JÀrgmise sÔna soovitused"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Kasuta soovituste tÀiustamiseks eelmist sÔna"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"JÀrgmise sÔna ennustus"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Kasuta ennustuseks ka eelmist sÔna"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : salvestatud"</string>
<string name="label_go_key" msgid="1635148082137219148">"Mine"</string>
<string name="label_next_key" msgid="362972844525672568">"Edasi"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"KÔnesisend on keelatud"</string>
<string name="configure_input_method" msgid="373356270290742459">"Sisestusmeetodite seadistamine"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Sisestuskeeled"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"MĂ€rgi ajatempel logisse"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Salvestatud ajatemplid"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ära logi seda seanssi"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Seansi logi kustutamine"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Seansi logi kustutatud"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Seansi logi EI kustutatud"</string>
<string name="select_language" msgid="3693815588777926848">"Sisestuskeeled"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Salvestamiseks puudutage uuesti"</string>
<string name="has_dictionary" msgid="6071847973466625007">"SÔnastik saadaval"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index bc0e85b77..6cb9e552b 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Ű”ÙŰ­Ù‡ Ú©Ù„ÛŒŰŻ (Android (AOSP"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ŰȘÙ†ŰžÛŒÙ…Ű§ŰȘ Ű”ÙŰ­Ù‡ Ú©Ù„ÛŒŰŻ Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ÚŻŰČینه Ù‡Ű§ÛŒ ÙˆŰ±ÙˆŰŻÛŒ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ÙŰ±Ù…Ű§Ù†â€ŒÙ‡Ű§ÛŒ ÚŻŰČŰ§Ű±ŰŽâ€ŒÚŻÛŒŰ±ÛŒ ÙŸÚ˜ÙˆÙ‡ŰŽ"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"ŰșÙ„Ű·â€ŒÚŻÛŒŰ± Ű§Ù…Ù„Ű§ÛŒ Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"ŰșÙ„Ű·â€ŒÚŻÛŒŰ± Ű§Ù…Ù„Ű§ÛŒ Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ŰȘÙ†ŰžÛŒÙ…Ű§ŰȘ ŰșÙ„Ű· ÚŻÛŒŰ±ÛŒ Ű§Ù…Ù„Ű§ÛŒÛŒ"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ÙŸÛŒŰŽ ÙŰ±Ű¶"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ÙŸÛŒŰŽÙ†Ù‡Ű§ŰŻ Ù†Ű§Ù… Ù‡Ű§ÛŒ Ù…ŰźŰ§Ű·Űš"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ŰšŰ±Ű§ÛŒ ÙŸÛŒŰŽÙ†Ù‡Ű§ŰŻ و ŰȘŰ”Ű­ÛŒŰ­ ۧŰČ Ù†Ű§Ù… Ù…ŰźŰ§Ű·ŰšÛŒÙ† ۧ۳ŰȘÙŰ§ŰŻÙ‡ ŰŽÙˆŰŻ"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"فŰčŰ§Ù„ Ú©Ű±ŰŻÙ† ŰȘŰ”Ű­ÛŒŰ­ Ù…ŰŹŰŻŰŻ"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ŰȘÙ†ŰžÛŒÙ… ÙŸÛŒŰŽÙ†Ù‡Ű§ŰŻŰ§ŰȘ ŰšŰ±Ű§ÛŒ ŰȘŰ”Ű­ÛŒŰ­ Ù…ŰŹŰŻŰŻ"</string>
<string name="auto_cap" msgid="1719746674854628252">"Ù†ÙˆŰŽŰȘن ۚۧ Ű­Ű±ÙˆÙ ŰšŰČ۱گ ŰźÙˆŰŻÚ©Ű§Ű±"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ÙŰ±Ù‡Ù†ÚŻâ€ŒÙ‡Ű§ÛŒ لŰșŰȘ Ű§ÙŰČÙˆŰŻÙ†ÛŒ"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ÙŰ±Ù‡Ù†ÚŻâ€Œ لŰșŰȘ Ű§Ű”Ù„ÛŒ"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"مŰȘÙˆŰłŰ·"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"فŰčŰ§Ù„"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"ŰšŰłÛŒŰ§Ű± ÙŸŰ±ŰźŰ§ŰŽÚŻŰ±Ű§Ù†Ù‡"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"ÙŸÛŒŰŽÙ†Ù‡Ű§ŰŻŰ§ŰȘ کلمه ŰšŰčŰŻÛŒ"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ŰšŰ±Ű§ÛŒ ŰšÙ‡ŰšÙˆŰŻ ÙŸÛŒŰŽÙ†Ù‡Ű§ŰŻ ۧŰČ Ú©Ù„Ù…Ù‡ Ù‚ŰšÙ„ÛŒ ۧ۳ŰȘÙŰ§ŰŻÙ‡ ŰŽÙˆŰŻ"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ÙŸÛŒŰŽâ€ŒŰšÛŒÙ†ÛŒ کلمه ŰšŰčŰŻÛŒ"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ۧ۳ŰȘÙŰ§ŰŻÙ‡ ۧŰČ Ú©Ù„Ù…Ù‡ Ù‚ŰšÙ„ÛŒ ŰšŰ±Ű§ÛŒ ÙŸÛŒŰŽ ŰšÛŒÙ†ÛŒ"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Ű°ŰźÛŒŰ±Ù‡ ŰŽŰŻ"</string>
<string name="label_go_key" msgid="1635148082137219148">"ŰšŰ±Ùˆ"</string>
<string name="label_next_key" msgid="362972844525672568">"ŰšŰčŰŻÛŒ"</string>
@@ -115,6 +114,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"ÙˆŰ±ÙˆŰŻÛŒ ۔ۯۧ ŰșÛŒŰ±ÙŰčŰ§Ù„ ۧ۳ŰȘ"</string>
<string name="configure_input_method" msgid="373356270290742459">"ÙŸÛŒÚ©Ű±ŰšÙ†ŰŻÛŒ Ű±ÙˆŰŽ Ù‡Ű§ÛŒ ÙˆŰ±ÙˆŰŻÛŒ"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ŰČŰšŰ§Ù† Ù‡Ű§ÛŒ ÙˆŰ±ÙˆŰŻÛŒ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ÛŒŰ§ŰŻŰŻŰ§ŰŽŰȘ Ù…Ù‡Ű± ŰČÙ…Ű§Ù† ۯ۱ ÚŻŰČۧ۱ێ"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Ù…Ù‡Ű± ŰČÙ…Ű§Ù† ۫ۚŰȘ ŰŽŰŻÙ‡"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ۧŰČ Ű§ÛŒÙ† ŰŹÙ„ŰłÙ‡ ÚŻŰČŰ§Ű±ŰŽâ€ŒÚŻÛŒŰ±ÛŒ Ù†ŰŽÙˆŰŻ"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"ۯ۱ Ű­Ű§Ù„ Ű­Ű°Ù ÚŻŰČۧ۱ێ ŰŹÙ„ŰłÙ‡"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ÚŻŰČۧ۱ێ ŰŹÙ„ŰłÙ‡ Ű­Ű°Ù ŰŽŰŻ"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"ÚŻŰČۧ۱ێ ŰŹÙ„ŰłÙ‡ Ű­Ű°Ù Ù†ŰŽŰŻ"</string>
<string name="select_language" msgid="3693815588777926848">"ŰČŰšŰ§Ù†â€ŒÙ‡Ű§ÛŒ ÙˆŰ±ÙˆŰŻÛŒ"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ŰšŰ±Ű§ÛŒ Ű°ŰźÛŒŰ±Ù‡ ŰŻÙˆŰšŰ§Ű±Ù‡ Ù„Ù…Űł Ú©Ù†ÛŒŰŻ"</string>
<string name="has_dictionary" msgid="6071847973466625007">"ŰŻÛŒÚ©ŰŽÙ†Ű±ÛŒ Ù…ÙˆŰŹÙˆŰŻ ۧ۳ŰȘ"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 97002edfe..4ee768e71 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-nÀppÀimistö (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android-nÀppÀimistön asetukset"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Syöttövalinnat"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Tutkimuslokin komennot"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android-oikoluku"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-oikoluku (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Oikoluvun asetukset"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Oletus"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Ehdota yhteystietojen nimiÀ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"KÀytÀ yhteystietojen nimiÀ ehdotuksissa ja korjauksissa"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Ota korjaukset kÀyttöön"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Aseta korjausehdotuksia"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automaattiset isot kirjaimet"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"LisÀsanakirjat"</string>
<string name="main_dictionary" msgid="4798763781818361168">"PÀÀsanakirja"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Osittainen"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"TĂ€ysi"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Hyvin aggressiivinen"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Seuraavan sanan ehdotukset"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Paranna ehdotuksia aiempien sanojen avulla"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Seuraavan sanan ennakointi"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"KÀytÀ edellistÀ sanaa myös ennakointiin"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Tallennettu"</string>
<string name="label_go_key" msgid="1635148082137219148">"Siirry"</string>
<string name="label_next_key" msgid="362972844525672568">"Seur."</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"ÄÀniohjaus on pois kĂ€ytöstĂ€"</string>
<string name="configure_input_method" msgid="373356270290742459">"MÀÀritÀ syöttötavat"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Syöttökielet"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Merkitse aikaleima lokiin"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Merkitty aikaleima"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ÄlĂ€ tallenna tĂ€tĂ€ kĂ€yttök."</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Poistetaan lokia"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"KÀyttökertaloki poistettu"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Lokia EI poistettu"</string>
<string name="select_language" msgid="3693815588777926848">"Syöttökielet"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Tallenna koskettamalla uudelleen"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Sanakirja saatavilla"</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 285d2226c..7273986d7 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Clavier Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ParamĂštres du clavier Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Commandes journaux rech."</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Correcteur orthographique Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Correcteur orthographique Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ParamĂštre du correcteur orthographique"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Proposer noms de contacts"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utiliser des noms de contacts pour les suggestions et corrections"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Activer la recorrection"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Définir des suggestions de recorrection"</string>
<string name="auto_cap" msgid="1719746674854628252">"Majuscules auto"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Dictionnaires complémentaires"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Dictionnaire principal"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Simple"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Proactive"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"TrĂšs exigeante"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Suggestions pour le mot suivant"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Améliorer les suggestions grùce au mot précédent"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Prédiction du mot suivant"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utiliser le mot précédent pour la prédiction"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : enregistré"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Suiv."</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Saisie vocale désactivée"</string>
<string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Noter heure dans journal"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Heure enregistrée."</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ne pas enregistrer session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Suppr. journal session
"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Journal session supprimé."</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Journal session PAS suppr."</string>
<string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 2b1808460..bf1058a98 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android à€•à„€à€Źà„‹à€°à„à€Ą (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android à€•à„€à€Źà„‹à€°à„à€Ą à€žà„‡à€Ÿà€żà€‚à€—"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"à€‡à€šà€Șà„à€Ÿ à€”à€żà€•à€Čà„â€à€Ș"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"à€Čà„‰à€— à€†à€Šà„‡à€¶à„‹à€‚ à€•à€Ÿ à€¶à„‹à€§ à€•à€°à„‡à€‚"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android à€”à€°à„à€€à€šà„€ à€Șà€°à„€à€•à„à€·à€•"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android à€”à€°à„à€€à€šà„€ à€Șà€°à„€à€•à„à€·à€• (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"à€”à€°à„à€€à€šà„€ à€œà€Ÿà€‚à€š à€žà„‡à€Ÿà€żà€‚à€—"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"à€Ąà€żà€«à€Œà„‰à€Čà„à€Ÿ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"à€žà€‚à€Șà€°à„à€• à€šà€Ÿà€ź à€žà„à€à€Ÿà€à€‚"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"à€žà„à€à€Ÿà€” à€”à€° à€žà„à€§à€Ÿà€° à€•à„‡ à€Čà€żà€ à€žà€‚à€Șà€°à„à€• à€žà„‡ à€šà€Ÿà€źà„‹à€‚ à€•à€Ÿ à€‰à€Șà€Żà„‹à€— à€•à€°à„‡à€‚"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"à€Șà„à€š: à€žà„à€§à€Ÿà€° à€žà€•à„à€·à€ź à€•à€°à„‡à€‚"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"à€Șà„à€š: à€žà„à€§à€Ÿà€° à€•à„‡ à€Čà€żâ€à€ à€žà„à€à€Ÿà€” à€žà„‡à€Ÿ à€•à€°à„‡à€‚"</string>
<string name="auto_cap" msgid="1719746674854628252">"à€žà„â€à€”à€€: à€…à€•à„à€·à€° à€Źà€Ąà€Œà„‡ à€•à€°à€šà€Ÿ"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"à€à€Ą-à€‘à€š à€Ąà€żà€•à„à€¶à€šà€°à„€"</string>
<string name="main_dictionary" msgid="4798763781818361168">"à€źà„à€–à„â€à€Ż à€Ąà€żà€•à„â€à€¶à€šà€°à„€"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"à€žà€Ÿà€§à€Ÿà€°à€Ł"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"à€€à„€à€”à„à€°"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"à€Źà€čà„à€€ à€€à„€à€”à„à€°"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"à€…à€—à€Čà€Ÿ à€¶à€Źà„â€à€Š à€žà„à€à€Ÿà€”"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"à€žà„à€à€Ÿà€”à„‹à€‚ à€•à„‹ à€Źà„‡à€čà€€à€° à€Źà€šà€Ÿà€šà„‡ à€•à„‡ à€Čà€żà€ à€Șà€żà€›à€Čà„‡ à€¶à€Źà„â€à€Š à€•à€Ÿ à€‰à€Șà€Żà„‹à€— à€•à€°à„‡à€‚"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"à€…à€—à€Čà€Ÿ à€¶à€Źà„â€à€Š à€Șà„‚à€°à„à€”à€Ÿà€šà„à€źà€Ÿà€š"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"à€Șà„‚à€°à„à€”à€Ÿà€šà„à€źà€Ÿà€š à€•à„‡ à€Čà€żà€ à€Șà€żà€›à€Čà„‡ à€¶à€Źà„à€Š à€•à€Ÿ à€‰à€Șà€Żà„‹à€— à€•à€°à„‡à€‚"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: à€žà€čà„‡à€œà€Ÿ à€—à€Żà€Ÿ"</string>
<string name="label_go_key" msgid="1635148082137219148">"à€œà€Ÿà€à€‚"</string>
<string name="label_next_key" msgid="362972844525672568">"à€…à€—à€Čà€Ÿ"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"à€§à„â€à€”à€šà€ż à€‡à€šà€Șà„à€Ÿ à€…à€•à„à€·à€ź à€čà„ˆ"</string>
<string name="configure_input_method" msgid="373356270290742459">"à€‡à€šà€Șà„à€Ÿ à€Șà€Šà„à€§à€€à€ż à€•à„‰à€šà„â€à€«à€Œà€żà€—à€° à€•à€°à„‡à€‚"</string>
<string name="language_selection_title" msgid="1651299598555326750">"à€‡à€šà€Șà„à€Ÿ à€­à€Ÿà€·à€Ÿ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"à€Čà„‰à€— à€źà„‡à€‚ à€Ÿà€Ÿà€‡à€źà€žà„â€à€Ÿà„ˆà€źà„â€à€Ș à€šà„‹à€Ÿ à€•à€°à„‡à€‚"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"à€°à€żà€•à„‰à€°à„à€Ą à€•à€żà€Żà€Ÿ à€—à€Żà€Ÿ à€Ÿà€Ÿà€‡à€źà€žà„à€Ÿà„ˆà€źà„à€Ș"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"à€‡à€ž à€žà€€à„à€° à€•à„‹ à€Čà„‰à€— à€š à€•à€°à„‡à€‚"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"à€žà€€à„à€° à€Čà„‰à€— à€čà€Ÿà€Ÿà€Żà€Ÿ à€œà€Ÿ à€°à€čà€Ÿ à€čà„ˆ"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"à€žà€€à„à€° à€Čà„‰à€— à€čà€Ÿà€Ÿà€Żà€Ÿ à€—à€Żà€Ÿ"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"à€žà€€à„à€° à€Čà„‰à€— à€čà€Ÿà€Ÿà€Żà€Ÿ à€šà€čà„€à€‚ à€—à€Żà€Ÿ"</string>
<string name="select_language" msgid="3693815588777926848">"à€‡à€šà€Șà„à€Ÿ à€­à€Ÿà€·à€Ÿà€à€‚"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"à€žà€čà„‡à€œà€šà„‡ à€•à„‡ à€Čà€żà€ à€Șà„à€š: à€žà„â€à€Șà€°à„à€¶ à€•à€°à„‡à€‚"</string>
<string name="has_dictionary" msgid="6071847973466625007">"à€¶à€Źà„â€à€Šà€•à„‹à€¶ à€‰à€Șà€Čà€Źà„â€à€§ à€čà„ˆ"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index a59d4698f..50f4c285d 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tipkovnica (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Postavke tipkovnice za Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcije ulaza"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"IstraĆŸivanje naredbi dnevnika"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Androidova provjera pravopisa"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidova provjera pravopisa (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Postavke provjere pravopisa"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Zadano"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"PredlaĆŸi imena kontakata"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Upotreba imena iz Kontakata za prijedloge i ispravke"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Omogući ponovne ispravke"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Postavite prijedloge za ponovne ispravke"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatsko pisanje velikih slova"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Rječnici-dodaci"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Glavni rječnik"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Skromno"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivno"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Vrlo agresivno"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Prijedlozi za sljedeću riječ"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Upotrijebi prethodnu riječ radi poboljơanja prijedloga"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Predviđanje sljedeće riječi"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Upotrijebite prethodnu riječ i za predviđanje"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Spremljeno"</string>
<string name="label_go_key" msgid="1635148082137219148">"Idi"</string>
<string name="label_next_key" msgid="362972844525672568">"Dalje"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. unos onemog."</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfiguriraj načine ulaza"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Jezici unosa"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ZabiljeĆŸi razdoblje u dnevniku"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ZabiljeĆŸeno razdoblje"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ne biljeĆŸi ovu sesiju"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Brisanje dnevnika sesije"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Izbrisan dnevnik sesije"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Dnevnik sesije NIJE izbrisan"</string>
<string name="select_language" msgid="3693815588777926848">"Jezici unosa"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Dodirnite ponovo za spremanje"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Rječnik je dostupan"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 0eac1a95b..834fa9e73 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-billentyƱzet (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android billentyƱzetbeållítåsok"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Beviteli beĂĄllĂ­tĂĄsok"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"NaplĂłzĂĄsi parancsok"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Androidos helyesírás-ellenƑrzƑ"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidos helyesírás-ellenƑrzƑ (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"HelyesĂ­rĂĄs-ellenƑrzĂ©s beĂĄllĂ­tĂĄsai"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"AlapbeĂĄllĂ­tĂĄs"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Javasolt névjegyek"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"A névjegyek hasznålata a javaslatokhoz és javítåsokhoz"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ÚjbĂłli javĂ­tĂĄs engedĂ©lyezĂ©se"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Javaslatok beĂĄllĂ­tĂĄsa az ĂșjbĂłli javĂ­tĂĄsokhoz"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatikusan nagy kezdƑbetƱ"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"BƑvĂ­tmĂ©nyek: szĂłtĂĄrak"</string>
<string name="main_dictionary" msgid="4798763781818361168">"FƑ szótár"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mérsékelt"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"AgresszĂ­v"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Nagyon agresszĂ­v"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"KövetkezƑ szĂłra vonatkozĂł javaslatok"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Javaslatok fejlesztĂ©se az elƑzƑ szĂł hasznĂĄlatĂĄval"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"KövetkezƑ szĂł elƑrejelzĂ©se"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Az elƑzƑ szó használata a prediktív bevitelhez is"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : mentve"</string>
<string name="label_go_key" msgid="1635148082137219148">"UgrĂĄs"</string>
<string name="label_next_key" msgid="362972844525672568">"TovĂĄbb"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hangbevivel KI"</string>
<string name="configure_input_method" msgid="373356270290742459">"Beviteli mĂłdok beĂĄllĂ­tĂĄsa"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Beviteli nyelvek"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"IdƑbĂ©lyegzƑ naplĂłzĂĄskor"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"RögzĂ­tett idƑbĂ©lyegzƑk"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ne naplĂłzza"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Napló törlése folyamatban"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Napló törölve"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Napló NINCS törölve"</string>
<string name="select_language" msgid="3693815588777926848">"Beviteli nyelvek"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Érintse meg ĂșjbĂłl a mentĂ©shez"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Van elĂ©rhetƑ szĂłtĂĄr"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index e0e92b5bd..6fed05506 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Keyboard Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Setelan keyboard Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opsi masukan"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Riset Perintah Log"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Pemeriksa ejaan Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pemeriksa ejaan Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Setelan pemeriksaan ejaan"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kontak"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kontak untuk saran dan koreksi"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Aktifkan koreksi ulang"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setel saran untuk koreksi ulang"</string>
<string name="auto_cap" msgid="1719746674854628252">"Kapitalisasi otomatis"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Kamus pengaya"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Sederhana"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sangat agresif"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Saran kata berikutnya"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gunakan kata sebelumnya untuk meningkatkan saran"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Prediksi kata berikutnya"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gunakan kata sebelumnya juga untuk prediksi"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Telah disimpan"</string>
<string name="label_go_key" msgid="1635148082137219148">"Buka"</string>
<string name="label_next_key" msgid="362972844525672568">"Berikutnya"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Masukan suara dinonaktifkan"</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan metode masukan"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Bahasa masukan"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Catat cap waktu di log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Cap waktu yang direkam"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Jangan simpan log sesi ini"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Menghapus log sesi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Log sesi dihapus"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Log sesi BELUM dihapus"</string>
<string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Kamus yang tersedia"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index a54958c05..3c9339fe6 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastiera Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Impostazioni tastiera Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opzioni inserimento"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Ricerca comandi di log"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Controllo ortografico Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Controllo ortografico Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Impostazioni di controllo ortografico"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinito"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Suggerisci nomi di contatti"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizza nomi di Contatti per suggerimenti e correzioni"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Attiva nuove correzioni"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Imposta suggerimenti per nuove correzioni"</string>
<string name="auto_cap" msgid="1719746674854628252">"Maiuscole automatiche"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Dizionari aggiuntivi"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Dizionario principale"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Media"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Massima"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Massima"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Suggerimenti parola successiva"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usa parola precedente per migliorare suggerimenti"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Previsione parola successiva"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Usa anche la parola precedente per la previsione"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : parola salvata"</string>
<string name="label_go_key" msgid="1635148082137219148">"Vai"</string>
<string name="label_next_key" msgid="362972844525672568">"Avanti"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Comandi vocali disatt."</string>
<string name="configure_input_method" msgid="373356270290742459">"Configura metodi di immissione"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Lingue comandi"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Indicazione temporale log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Indicazione temporale registrata"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Non registrare la sessione"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Eliminazione log sessione"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Log di sessione eliminato"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Log sessione non eliminato"</string>
<string name="select_language" msgid="3693815588777926848">"Lingue comandi"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Tocca di nuovo per salvare"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index 323cac198..da00346d0 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"ŚžŚ§ŚœŚ“ŚȘ Android ‏(AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Ś”Ś’Ś“ŚšŚ•ŚȘ ŚžŚ§ŚœŚ“ŚȘ کڜ Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ŚŚ€Ś©ŚšŚ•Ś™Ś•ŚȘ ڧڜژ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ڀڧڕړڕŚȘ Ś™Ś•ŚžŚŸ ŚžŚ—Ś§Śš"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"ڑڕړڧ ڔڐڙڕŚȘ کڜ Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"ڑڕړڧ ڔڐڙڕŚȘ کڜ Android ‏(AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Ś”Ś’Ś“ŚšŚ•ŚȘ ڑړڙڧŚȘ ڐڙڕŚȘ"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Ś‘ŚšŚ™ŚšŚȘ ŚžŚ—Ś“Śœ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Ś”ŚŠŚą Ś©ŚžŚ•ŚȘ کڜ ڐڠکڙ Ś§Ś©Śš"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ڔکŚȘŚžŚ© Ś‘Ś©ŚžŚ•ŚȘ ŚžŚšŚ©Ś™ŚžŚȘ ڐڠکڙ Ś”Ś§Ś©Śš ŚąŚ‘Ś•Śš Ś”ŚŠŚąŚ•ŚȘ Ś•ŚȘŚ™Ś§Ś•Ś Ś™Ś"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Ś”Ś€Ś•Śš ŚȘŚ™Ś§Ś•Ś Ś™Ś Ś—Ś•Ś–ŚšŚ™Ś ŚœŚ€ŚąŚ™ŚœŚ™Ś"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ś”Ś’Ś“Śš Ś”ŚŠŚąŚ•ŚȘ ŚąŚ‘Ś•Śš ŚȘŚ™Ś§Ś•Ś Ś™Ś Ś—Ś•Ś–ŚšŚ™Ś"</string>
<string name="auto_cap" msgid="1719746674854628252">"ڔڀڙڛŚȘ ڐڕŚȘڙڕŚȘ ŚœŚšŚ™Ś©Ś™Ś•ŚȘ Ś‘ŚŚ•Ś€ŚŸ ŚŚ•Ś˜Ś•ŚžŚ˜Ś™"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Ś”Ś•ŚĄŚ€ŚȘ ŚžŚ™ŚœŚ•Ś Ś™Ś"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ŚžŚ™ŚœŚ•ŚŸ ŚšŚŚ©Ś™"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ŚžŚŠŚ•ŚžŚŠŚ"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"ŚžŚ—ŚžŚ™Śš"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"ŚžŚ—ŚžŚ™Śš ŚžŚŚ•Ś“"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Ś”ŚŠŚąŚ•ŚȘ Ś”ŚžŚ™ŚœŚ” ڔڑڐڔ"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ڔکŚȘŚžŚ© Ś‘ŚžŚ™ŚœŚ” Ś”Ś§Ś•Ś“ŚžŚȘ ڛړڙ ŚœŚ©Ś€Śš ڐŚȘ Ś”Ś”ŚŠŚąŚ•ŚȘ"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ڗڙږڕڙ Ś”ŚžŚ™ŚœŚ” ڔڑڐڔ"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ڔکŚȘŚžŚ© Ś‘ŚžŚ™ŚœŚ” Ś”Ś§Ś•Ś“ŚžŚȘ Ś’Ś ŚąŚ‘Ś•Śš ڗڙږڕڙ"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Ś Ś©ŚžŚšŚ”"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ś‘ŚŠŚą"</string>
<string name="label_next_key" msgid="362972844525672568">"ڔڑڐ"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Ś”Ś§ŚœŚ˜ Ś”Ś§Ś•ŚœŚ™ ŚžŚ•Ś©Ś‘ŚȘ"</string>
<string name="configure_input_method" msgid="373356270290742459">"Ś”Ś’Ś“ŚšŚȘ Ś©Ś™Ś˜Ś•ŚȘ ڧڜژ"</string>
<string name="language_selection_title" msgid="1651299598555326750">"کڀڕŚȘ ڧڜژ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ŚŠŚ™Ś™ŚŸ Ś—Ś•ŚȘŚžŚȘ Ś–ŚžŚŸ Ś‘Ś™Ś•ŚžŚŸ"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Ś—Ś•ŚȘŚžŚȘ Ś–ŚžŚŸ ŚžŚȘŚ•ŚąŚ“ŚȘ"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ڐڜ ŚȘŚšŚ©Ś•Ś Ś”Ś€ŚąŚœŚ” Ś–Ś• Ś‘Ś™Ś•ŚžŚŸ"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"ŚžŚ•Ś—Ś§ Ś™Ś•ŚžŚŸ Ś”Ś€ŚąŚœŚ”"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Ś™Ś•ŚžŚŸ Ś”Ś€ŚąŚœŚ” Ś ŚžŚ—Ś§"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Ś™Ś•ŚžŚŸ Ś”Ś€ŚąŚœŚ” ڜڐ Ś ŚžŚ—Ś§"</string>
<string name="select_language" msgid="3693815588777926848">"کڀڕŚȘ ڧڜژ"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Ś’Śą کڕڑ ڛړڙ ŚœŚ©ŚžŚ•Śš"</string>
<string name="has_dictionary" msgid="6071847973466625007">"ŚžŚ™ŚœŚ•ŚŸ Ś–ŚžŚ™ŚŸ"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 3a865166f..54e07d494 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androidă‚­ăƒŒăƒœăƒŒăƒ‰ïŒˆAOSP"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Androidă‚­ăƒŒăƒœăƒŒăƒ‰ăźèš­ćźš"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"慄抛ă‚Șăƒ—ă‚·ăƒ§ăƒł"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ăƒ­ă‚°ă‚łăƒžăƒłăƒ‰ăźæ€œçŽą"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Androidă‚čăƒšăƒ«ăƒă‚§ăƒƒă‚«ăƒŒ"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidă‚čăƒšăƒ«ăƒă‚§ăƒƒă‚«ăƒŒïŒˆAOSP"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ă‚čăƒšăƒ«ăƒă‚§ăƒƒă‚Żăźèš­ćźš"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ăƒ‡ăƒ•ă‚©ăƒ«ăƒˆ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ć€™èŁœăźé€Łç”Ąć…ˆćă‚’èĄšç€ș"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"é€Łç”Ąć…ˆăźćć‰ă‚’äœżç”šă—ăŠć€™èŁœèĄšç€șやè‡Șć‹•äżźæ­Łă‚’èĄŒă„ăŸă™"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ć†äżźæ­Łă‚’æœ‰ćŠčにする"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ć†äżźæ­Łăźć€™èŁœă‚’æŒżć…„ă™ă‚‹"</string>
<string name="auto_cap" msgid="1719746674854628252">"è‡Șć‹•ć€§æ–‡ć­—ć€‰æ›"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ケドă‚ȘăƒłèŸžæ›ž"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ăƒĄă‚€ăƒłèŸžæ›ž"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"äž­"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"ćŒ·"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"æœ€ă‚‚ćŒ·ă„"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"æŹĄăźć…„ćŠ›ć€™èŁœ"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"目才ぼ捘èȘžă‹ă‚‰ć…„ćŠ›ć€™èŁœă‚’äșˆæžŹă—ăŸă™"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"æŹĄăźć…„ćŠ›ć€™èŁœă‚’äșˆæžŹ"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"才ぼèȘžć„もäșˆæžŹă«äœżç”š"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:äżć­˜ă—ăŸă—ăŸ"</string>
<string name="label_go_key" msgid="1635148082137219148">"ćźŸèĄŒ"</string>
<string name="label_next_key" msgid="362972844525672568">"æŹĄăž"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"éŸłćŁ°ć…„ćŠ›ăŻç„ĄćŠčです"</string>
<string name="configure_input_method" msgid="373356270290742459">"慄抛æ–čæł•ă‚’èš­ćźš"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ć…„ćŠ›èš€èȘž"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ă‚żă‚€ăƒ ă‚čă‚żăƒłăƒ—ă‚’èš˜éŒČ"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ă‚żă‚€ăƒ ă‚čă‚żăƒłăƒ—èš˜éŒČæžˆăż"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ă‚»ăƒƒă‚·ăƒ§ăƒłă‚’èš˜éŒČしăȘい"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"ă‚»ăƒƒă‚·ăƒ§ăƒłăƒ­ă‚°ć‰Šé™€äž­"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ă‚»ăƒƒă‚·ăƒ§ăƒłăƒ­ă‚°ć‰Šé™€æžˆăż"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"ă‚»ăƒƒă‚·ăƒ§ăƒłăƒ­ă‚°æœȘ扊陀"</string>
<string name="select_language" msgid="3693815588777926848">"ć…„ćŠ›èš€èȘž"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"äżć­˜ă™ă‚‹ă«ăŻă‚‚ă†äž€ćșŠă‚żăƒƒăƒ—"</string>
<string name="has_dictionary" msgid="6071847973466625007">"èŸžæ›žă‚’ćˆ©ç”šă§ăăŸă™"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 536f06dbd..09ee97f39 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android í‚€ëłŽë“œ(AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android í‚€ëłŽë“œ 섀정"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ìž…ë „ 옔션"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ëĄœê·ž ëȘ…ë č 탐색"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android 맞춀ëȕ êČ€ì‚Źêž°"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 맞춀ëȕ êČ€ì‚Źêž°(AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"맞춀ëȕ êČ€ì‚Ź 섀정"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"êž°ëłžê°’"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ìŁŒì†ŒëĄ 읎늄 활용"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"추ìȜ 및 수정에 ìŁŒì†ŒëĄì˜ 읎늄 ì‚Źìš©"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ìžŹìˆ˜ì • 가늄 섀정"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ìžŹìˆ˜ì • 추ìČœì–Ž ì‚Źì „ 활성화"</string>
<string name="auto_cap" msgid="1719746674854628252">"자동 ëŒ€ëŹžìží™”"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ì‚Źì „ 추가"</string>
<string name="main_dictionary" msgid="4798763781818361168">"êž°ëłž ì‚Źì „"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"앜"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"쀑"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"강"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"닀음 추ìȜ êČ€ìƒ‰ì–Ž"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"읎전 닚얎넌 ì‚Źìš©í•˜ì—Ź 추ìȜ êČ€ìƒ‰ì–Ž 개선"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"닀음 예상 êČ€ìƒ‰ì–Ž"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"읎전 닚얎넌 ì‚Źìš©í•˜ì—Ź 예상 êČ€ìƒ‰ì–Ž 표시"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: 저임됚"</string>
<string name="label_go_key" msgid="1635148082137219148">"읎동"</string>
<string name="label_next_key" msgid="362972844525672568">"닀음"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"음성 입렄읎 ì‚Źìš© 쀑지됚"</string>
<string name="configure_input_method" msgid="373356270290742459">"ìž…ë „ ë°©ëȕ 섀정"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ìž…ë „ ì–žì–Ž"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ëĄœê·žì— íƒ€ìž„ìŠ€íƒŹí”„ë„Œ êž°ëĄ"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"íƒ€ìž„ìŠ€íƒŹí”„ë„Œ êž°ëĄí•š"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"읎 섞션을 ëĄœê·ží•˜ì§€ 마섞요."</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"섞션 ëĄœê·ž 삭제"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"섞션 ëĄœê·žê°€ 삭제됚"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"섞션 ëĄœê·žê°€ 삭제되지 않음"</string>
<string name="select_language" msgid="3693815588777926848">"ìž…ë „ ì–žì–Ž"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"저임하렀멎 닀시 터ìč˜"</string>
<string name="has_dictionary" msgid="6071847973466625007">"ì‚Źì „ ì‚Źìš© 가늄"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index a0b8fc87d..ff7b48a9b 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"„Android“ klaviatĆ«ra (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"„Android“ klaviatĆ«ros nustatymai"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Äźvesties parinktys"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Tyrinėti ĆŸurnalo komandas"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"„Android“ raơybos tikrinimo programa"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"„Android“ raơybos tikrinimo programa (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"RaĆĄybos tikrinimo nustatymai"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Numatytasis"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Siƫlyti kontaktƳ vardus"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"SiĆ«lant ir taisant naudoti vardus iĆĄ „KontaktƳ“"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Äźdiegti pakartotinius pataisymus"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nustatyti pakartotinio pataisymo pasiƫlymus"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatinis didĆŸiĆłjĆł raidĆŸiĆł raĆĄymas"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Papildomi ĆŸodynai"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Pagrindinis ĆŸodynas"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Vidutinis"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Atkaklus"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Labai agresyviai"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Kito ĆŸodĆŸio pasiĆ«lymai"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Naudoti ankstesnÄŻ ĆŸodÄŻ pasiĆ«lymams patobulinti"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Kito ĆŸodĆŸio numatymas"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Numatant naudoti ir ankstesnÄŻ ĆŸodÄŻ"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: iĆĄsaugota"</string>
<string name="label_go_key" msgid="1635148082137219148">"Pradėti"</string>
<string name="label_next_key" msgid="362972844525672568">"Kitas"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balso ÄŻv. neleidĆŸ."</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfigƫruoti įvesties metodus"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Äźvesties kalbos"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"PaĆŸym. laiko ĆŸymę ĆŸurnale"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ÄźraĆĄyta laiko ĆŸymė"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"NeÄŻraĆĄyti ĆĄios sesijos"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"IĆĄtrinam. sesijos ĆŸurnal."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sesijos ĆŸurnalas iĆĄtrint."</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sesij. ĆŸurnal. NEIĆ TRINT."</string>
<string name="select_language" msgid="3693815588777926848">"Äźvesties kalbos"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Jei norite iơsaugoti, palieskite dar kartą"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ćœodynas galimas"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 93727a8ba..2a6c8eaa1 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tastatƫra (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android tastatƫras iestatījumi"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Ievades opcijas"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Izpētes ĆŸurnāla komandas"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android pareizrakstības pārbaudītājs"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android pareizrakstības pārbaudītājs (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Pareizrakstības pārbaudes iestatījumi"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Noklusējums"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Ieteikt kontaktp. vārdus"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Izmantot kontaktpersonu vārdus kā ieteikumus un labojumus"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Iespējot atk. labojumus"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Iestatīt atkārtotu labojumu ieteikumus"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automātiska lielo burtu lietoƥana"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Papildinājumu vārdnīcas"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Galvenā vārdnīca"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mērena"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresīva"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Ļoti radikāla"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Nākamā vārda ieteikumi"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Ieteikumu uzlaboơanai izmantot iepriekơējo vārdu"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Nākamā vārda prognozēơana"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Izmantot iepriekơējo vārdu arÄ« prognozēm"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: saglabāts"</string>
<string name="label_go_key" msgid="1635148082137219148">"Sākt"</string>
<string name="label_next_key" msgid="362972844525672568">"Tālāk"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balss iev. atspējota"</string>
<string name="configure_input_method" msgid="373356270290742459">"Ievades metoĆŸu konfigurēơana"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Ievades valodas"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"AtzÄ«mēt laiksp. ĆŸurnālā"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Laikspied. ir reģistrēts."</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nereģistrēt ơo sesiju"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Not. sesijas ĆŸurn. dzēơ."</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sesijas ĆŸurnāls ir dzēsts"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sesijas ĆŸurn. NAV dzēsts"</string>
<string name="select_language" msgid="3693815588777926848">"Ievades valodas"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Pieskarieties vēlreiz, lai saglabātu."</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ir pieejama vārdnīca."</string>
diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml
index a07c44f2c..5809fe005 100644
--- a/java/res/values-ms/strings.xml
+++ b/java/res/values-ms/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Papan kekunci Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Tetapan papan kekunci Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Pilihan input"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Arahan Log Penyelidikan"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Penyemak ejaan Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Penyemak ejaan Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Tetapan penyemakan ejaan"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Lalai"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Cadangkan nama Kenalan"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama daripada Kenalan untuk cadangan dan pembetulan"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Dayakan pembetulan semula"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Tetapkan cadangan untuk pembetulan semula"</string>
<string name="auto_cap" msgid="1719746674854628252">"Huruf besar auto"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Kamus tambahan"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Sederhana"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Sangat agresif"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Cadangan perkataan seterusnya"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gunakan perkataan sebelumnya untuk memperbaik cadangan"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Ramalan perkataan seterusnya"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gunakan juga perkataan sebelumnya untuk ramalan"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Disimpan"</string>
<string name="label_go_key" msgid="1635148082137219148">"Pergi"</string>
<string name="label_next_key" msgid="362972844525672568">"Seterusnya"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input suara dilmphkn"</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan kaedah input"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Bahasa input"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Tanda cap waktu dalam log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Cap waktu direkodkan"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Jangan log sesi ini"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Memadam log sesi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Log sesi dipadam"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Log sesi TIDAK dipadam"</string>
<string name="select_language" msgid="3693815588777926848">"Bahasa input"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Kamus tersedia"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 75c1295a9..8d2b3f65b 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Innstillinger for skjermtastatur"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Inndataalternativer"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Kommandoer for undersĂžkelseslogging"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android-stavekontroll"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontroll (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Innstillinger for stavekontroll"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ForeslÄ kontaktnavn"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Bruk navn fra Kontakter til forslag og korrigeringer"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Aktiver korrigeringer"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Angi forslag for korrigeringer"</string>
<string name="auto_cap" msgid="1719746674854628252">"Stor forbokstav"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"TilleggsordbĂžker"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Hovedordliste"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderat"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Omfattende"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Veldig aggressiv"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Forslag til rettelser av neste ord"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Bruk forrige ord til Ă„ forbedre forslagene"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Forslag til neste ord"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Bruk forrige ord ogsÄ for forslag"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Lagret"</string>
<string name="label_go_key" msgid="1635148082137219148">"UtfĂžr"</string>
<string name="label_next_key" msgid="362972844525672568">"Neste"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Taleinndata er deaktiv."</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfigurer inndatametoder"</string>
<string name="language_selection_title" msgid="1651299598555326750">"InndatasprÄk"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Notér tidsstempel i logg"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Registrerte tidsstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ikke loggfĂžr denne Ăžkten"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sletter Ăžktloggen"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Øktloggen ble slettet"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Øktloggen ble IKKE slettet"</string>
<string name="select_language" msgid="3693815588777926848">"InndatasprÄk"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Trykk pÄ nytt for Ä lagre"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index a7d499bd0..b3ab6cab9 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-toetsenbord (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Instellingen voor Android-toetsenbord"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropties"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Opdrachten in onderzoekslogbestand"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Spellingcontrole van Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Spellingcontrole van Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Instellingen voor spellingcontrole"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standaard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Contactnamen suggereren"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Namen uit Contacten gebruiken voor suggesties en correcties"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Verbeteringen inschakelen"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Suggesties instellen voor verbeteringen"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-hoofdlettergebruik"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Woordenboeken toevoegen"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Algemeen woordenboek"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Normaal"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressief"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Zeer agressief"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Volgende woordsuggesties"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Vorig woord gebruiken om suggesties te verbeteren"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Volgende woordvoorspelling"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Het voorgaande woord ook voor voorspelling gebruiken"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: opgeslagen"</string>
<string name="label_go_key" msgid="1635148082137219148">"Start"</string>
<string name="label_next_key" msgid="362972844525672568">"Verder"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spraakinvoer is uit"</string>
<string name="configure_input_method" msgid="373356270290742459">"Invoermethoden configureren"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Invoertalen"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Tijdstempel opnemen in logbestand"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Opgenomen tijdstempel"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Sessie niet registreren"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Sessielogbestand verwijderen"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Sessielogbestand verwijderd"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Sessielogbestand NIET verwijderd"</string>
<string name="select_language" msgid="3693815588777926848">"Invoertalen"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak nogmaals aan om op te slaan"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index bf27782b6..6338f5d7d 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klawiatura Androida (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Ustawienia klawiatury Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Polecenia dziennika badaƄ"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"SƂownik Androida"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Sprawdzanie pisowni na Androidzie (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Ustawienia sprawdzania pisowni"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Wartoƛć domyƛlna"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Proponuj osoby z kontaktĂłw"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"W propozycjach i poprawkach uĆŒyj nazwisk z kontaktĂłw"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"WƂącz poprawki"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Ustaw sugestie poprawek"</string>
<string name="auto_cap" msgid="1719746674854628252">"Wstawiaj wielkie litery"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Dodatkowe sƂowniki"</string>
<string name="main_dictionary" msgid="4798763781818361168">"SƂownik gƂówny"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Umiarkowana"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresywna"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Bardzo agresywna"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestie kolejnych sƂów"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"UĆŒywaj poprzedniego wyrazu, by polepszyć sugestie"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Przewidywanie następnego wyrazu"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Przewiduj rĂłwnieĆŒ na podstawie poprzedniego sƂowa"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Zapisano"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Dalej"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Wprowadzanie gƂosowe jest wyƂączone"</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfiguruj metody wprowadzania"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Języki wprowadzania"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Znacznik czasu uwagi w dzienniku"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Zapisano znacznik czasu"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nie rejestruj tej sesji"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Usuwanie dziennika sesji"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Usunięto dziennik sesji"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Dziennik sesji NIEUSUNIĘTY"</string>
<string name="select_language" msgid="3693815588777926848">"Języki wprowadzania"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotknij ponownie, aby zapisać"</string>
<string name="has_dictionary" msgid="6071847973466625007">"SƂownik dostępny"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index ccb042e47..dcbdbc89e 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"DefiniçÔes de teclado do Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"OpçÔes de introdução"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comandos de Reg. Invest."</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Verificador ortogrĂĄfico do Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificador ortogrĂĄfico do Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"DefiniçÔes da verificação ortogråfica"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinido"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de Contactos"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizar nomes dos Contactos para sugestÔes e correçÔes"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Ativar correçÔes"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Definir sugestÔes para correçÔes"</string>
<string name="auto_cap" msgid="1719746674854628252">"Letras maiĂșsculas automĂĄticas"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"DicionĂĄrios extras"</string>
<string name="main_dictionary" msgid="4798763781818361168">"DicionĂĄrio principal"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderada"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressiva"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muito agressivo"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"SugestÔes da palavra seguinte"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilizar palavra anterior para melhorar sugestÔes"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"PrevisĂŁo da palavra seguinte"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Utilizar a palavra anterior também para predição"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Avançar"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. voz desact."</string>
<string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introdução"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Anotar car. data no reg."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Carimbo de data gravado"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"NĂŁo registar esta sessĂŁo"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"A eliminar reg. da sessĂŁo"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Reg. de sessĂŁo eliminado"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Reg. de sessão NÃO elim."</string>
<string name="select_language" msgid="3693815588777926848">"Idiomas de introdução"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para guardar"</string>
<string name="has_dictionary" msgid="6071847973466625007">"DicionĂĄrio disponĂ­vel"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index 7d64759d8..e55a75d37 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ConfiguraçÔes de teclado Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"OpçÔes de entrada"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Pesq. comandos de reg."</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Corretor ortogrĂĄfico do Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corretor ortogrĂĄfico do Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ConfiguraçÔes de verificação ortogråfica"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"PadrĂŁo"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nomes de contato"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nomes dos Contatos para sugestÔes e correçÔes"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Ativar recorreçÔes"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Definir sugestÔes para recorreçÔes"</string>
<string name="auto_cap" msgid="1719746674854628252">"Capitaliz. automĂĄtica"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"DicionĂĄrios complementares"</string>
<string name="main_dictionary" msgid="4798763781818361168">"DicionĂĄrio principal"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agressivo"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Muito agressivo"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"SugestÔes p/ palavra seguinte"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Usar palavra anterior para melhorar as sugestÔes"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"PrevisĂŁo da palavra seguinte"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Use também a palavra anterior para prever"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Salvo"</string>
<string name="label_go_key" msgid="1635148082137219148">"Ir"</string>
<string name="label_next_key" msgid="362972844525672568">"Avançar"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Texto por voz desat."</string>
<string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Indicar data/hora no reg."</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Data/hora registrada"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"NĂŁo registrar esta sessĂŁo"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Excluindo reg. de sessĂŁo"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Registro excluĂ­do"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Registro NÃO excluído"</string>
<string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para salvar"</string>
<string name="has_dictionary" msgid="6071847973466625007">"DicionĂĄrio disponĂ­vel"</string>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index 18741f816..b39691ceb 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -26,6 +26,8 @@
<string name="english_ime_settings" msgid="6661589557206947774">"Parameters da la tastatura Android"</string>
<!-- no translation found for english_ime_input_options (3909945612939668554) -->
<skip />
+ <!-- no translation found for english_ime_research_log (8492602295696577851) -->
+ <skip />
<!-- no translation found for spell_checker_service_name (7338064335159755926) -->
<skip />
<!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) -->
@@ -65,10 +67,6 @@
<skip />
<!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
<skip />
- <!-- no translation found for enable_span_insert (7204653105667167620) -->
- <skip />
- <!-- no translation found for enable_span_insert_summary (2947317657871394467) -->
- <skip />
<string name="auto_cap" msgid="1719746674854628252">"Maiusclas automaticas"</string>
<!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
<skip />
@@ -96,13 +94,9 @@
<skip />
<!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) -->
<skip />
- <!-- no translation found for bigram_suggestion (8169311444438922902) -->
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
<skip />
- <!-- no translation found for bigram_suggestion_summary (6635527607242625713) -->
- <skip />
- <!-- no translation found for bigram_prediction (3216364899483135294) -->
- <skip />
- <!-- no translation found for bigram_prediction_summary (1747261921174300098) -->
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
<skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : MemorisĂ "</string>
<string name="label_go_key" msgid="1635148082137219148">"Dai"</string>
@@ -190,6 +184,18 @@
<!-- no translation found for configure_input_method (373356270290742459) -->
<skip />
<string name="language_selection_title" msgid="1651299598555326750">"Linguas da cumonds vocals"</string>
+ <!-- no translation found for note_timestamp_for_researchlog (1889446857977976026) -->
+ <skip />
+ <!-- no translation found for notify_recorded_timestamp (8036429032449612051) -->
+ <skip />
+ <!-- no translation found for do_not_log_this_session (413762473641146336) -->
+ <skip />
+ <!-- no translation found for notify_session_log_deleting (3299507647764414623) -->
+ <skip />
+ <!-- no translation found for notify_session_log_deleted (8687927130100934686) -->
+ <skip />
+ <!-- no translation found for notify_session_log_not_deleted (2592908998810755970) -->
+ <skip />
<!-- no translation found for select_language (3693815588777926848) -->
<skip />
<!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 0c4d8bcfb..07c0c00a1 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastatură Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Setările tastaturii Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"OpĆŁiuni de introducere text"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Comenzi jurnal cercetare"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Verificator ortografic Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificator ortografic Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Setări de verificare ortografică"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Prestabilit"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sugeraƣi nume din Agendă"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizaƣi numele din Agendă pentru sugestii Ɵi corecƣii"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Activaƣi rectificările"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setaƣi sugestii pentru rectificări"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-capitalizare"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"DicĆŁionare suplimentare"</string>
<string name="main_dictionary" msgid="4798763781818361168">"DicĆŁionar principal"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderată"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivă"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Foarte exigentă"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Sugestii pentru cuvùntul următor"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Utilizaƣi cuvùntul anterior pentru a ßmbunătăƣi sugestiile"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Predicƣia cuvùntului următor"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Se utilizează Ɵi cuvñntul precedent pentru predicƣii"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: salvat"</string>
<string name="label_go_key" msgid="1635148082137219148">"OK"</string>
<string name="label_next_key" msgid="362972844525672568">"Înainte"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Intr. vocală dezact."</string>
<string name="configure_input_method" msgid="373356270290742459">"ConfiguraĆŁi metodele de intrare"</string>
<string name="language_selection_title" msgid="1651299598555326750">"SelectaĆŁi limba"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Înreg. marc. temp. jurnal"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Marcaj temporal Ăźnregis."</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Nu ĂźnregistraĆŁi sesiunea"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Se șterge jurnal sesiune"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Jurnal de sesiune șters"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Jurnal sesiune neßters"</string>
<string name="select_language" msgid="3693815588777926848">"Limbi de intrare"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"AtingeĆŁi din nou pentru a salva"</string>
<string name="has_dictionary" msgid="6071847973466625007">"DicĆŁionar disponibil"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index f76cc8eaf..69b4fe914 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"КлаĐČоатура Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"КлаĐČоатура Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ĐĐ°ŃŃ‚Ń€ĐŸĐčĐșĐž"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ВсД ĐșĐŸĐŒĐ°ĐœĐŽŃ‹"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"ĐŸŃ€ĐŸĐČДрĐșа праĐČĐŸĐżĐžŃĐ°ĐœĐžŃ Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"ĐŸŃ€ĐŸĐČДрĐșа праĐČĐŸĐżĐžŃĐ°ĐœĐžŃ Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ĐĐ°ŃŃ‚Ń€ĐŸĐčĐșа ĐżŃ€ĐŸĐČДрĐșĐž праĐČĐŸĐżĐžŃĐ°ĐœĐžŃ"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ĐŸĐŸ ŃƒĐŒĐŸĐ»Ń‡Đ°ĐœĐžŃŽ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ĐŸĐŸĐŽŃĐșазыĐČать ĐžĐŒĐ”ĐœĐ°"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ĐŸĐŸĐŽŃĐșазыĐČать оспраĐČĐ»Đ”ĐœĐžŃ ĐœĐ° ĐŸŃĐœĐŸĐČĐ” ĐžĐŒĐ”Đœ Оз спОсĐșа ĐșĐŸĐœŃ‚Đ°ĐșŃ‚ĐŸĐČ"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"АĐČŃ‚ĐŸĐžŃĐżŃ€Đ°ĐČĐ»Đ”ĐœĐžĐ”"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ĐŸĐŸĐșазыĐČать ĐČĐ°Ń€ĐžĐ°ĐœŃ‚Ń‹ оспраĐČĐ»Đ”ĐœĐžŃ"</string>
<string name="auto_cap" msgid="1719746674854628252">"ЗаглаĐČĐœŃ‹Đ” аĐČŃ‚ĐŸĐŒĐ°Ń‚ĐžŃ‡Đ”ŃĐșĐž"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Đ”ĐŸĐżĐŸĐ»ĐœĐžŃ‚Đ”Đ»ŃŒĐœŃ‹Đ” ŃĐ»ĐŸĐČаро"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ĐžŃĐœĐŸĐČĐœĐŸĐč ŃĐ»ĐŸĐČарь"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ĐŁĐŒĐ”Ń€Đ”ĐœĐœĐŸĐ”"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"АĐșтоĐČĐœĐŸĐ”"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"ĐžŃ‡Đ”ĐœŃŒ аĐșтоĐČĐœĐŸ"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"ĐĄĐ»Đ”ĐŽŃƒŃŽŃ‰ĐžĐ” ĐČĐ°Ń€ĐžĐ°ĐœŃ‚Ń‹"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Đ˜ŃĐżĐŸĐ»ŃŒĐ·ĐŸĐČать ĐżŃ€Đ”ĐŽŃ‹ĐŽŃƒŃ‰Đ”Đ” ŃĐ»ĐŸĐČĐŸ, Ń‡Ń‚ĐŸĐ±Ń‹ оспраĐČоть ĐżŃ€Đ”ĐŽĐ»ĐŸĐ¶Đ”ĐœĐœŃ‹Đ” ĐČĐ°Ń€ĐžĐ°ĐœŃ‚Ń‹"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ĐĄĐ»Đ”ĐŽŃƒŃŽŃ‰Đ°Ń ĐżĐŸĐŽŃĐșазĐșа"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Đ˜ŃĐżĐŸĐ»ŃŒĐ·ĐŸĐČать ĐżŃ€Đ”ĐŽŃ‹ĐŽŃƒŃ‰Đ”Đ” ŃĐ»ĐŸĐČĐŸ ĐŽĐ»Ń ĐżŃ€ĐŸĐłĐœĐŸĐ·ĐžŃ€ĐŸĐČĐ°ĐœĐžŃ"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: ŃĐŸŃ…Ń€Đ°ĐœĐ”ĐœĐŸ"</string>
<string name="label_go_key" msgid="1635148082137219148">"ĐŸĐŸĐžŃĐș"</string>
<string name="label_next_key" msgid="362972844525672568">"ДалДД"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Đ“ĐŸĐ»ĐŸŃĐŸĐČĐŸĐč ĐČĐČĐŸĐŽ ĐŸŃ‚ĐșĐ»."</string>
<string name="configure_input_method" msgid="373356270290742459">"ĐĐ°ŃŃ‚Ń€ĐŸĐčĐșа ŃĐżĐŸŃĐŸĐ±ĐŸĐČ ĐČĐČĐŸĐŽĐ°"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ĐŻĐ·Ń‹ĐșĐž ĐČĐČĐŸĐŽĐ°"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ЗаĐșлаЎĐșа ĐČ Đ¶ŃƒŃ€ĐœĐ°Đ»Đ”"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ЗаĐșлаЎĐșа ŃĐŸŃ…Ń€Đ°ĐœĐ”ĐœĐ°"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ĐĐ” ŃĐŸŃ…Ń€Đ°ĐœŃŃ‚ŃŒ ŃŃ‚ĐŸŃ‚ ŃĐ”Đ°ĐœŃ"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"ĐŁĐŽĐ°Đ»Đ”ĐœĐžĐ”â€Š"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Запось ŃĐ”Đ°ĐœŃĐ° ŃƒĐŽĐ°Đ»Đ”ĐœĐ°"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Запось ŃĐ”Đ°ĐœŃĐ° НЕ ŃƒĐŽĐ°Đ»Đ”ĐœĐ°"</string>
<string name="select_language" msgid="3693815588777926848">"ĐŻĐ·Ń‹ĐșĐž ĐČĐČĐŸĐŽĐ°"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ĐĐ°Đ¶ĐŒĐžŃ‚Đ”, Ń‡Ń‚ĐŸĐ±Ń‹ ŃĐŸŃ…Ń€Đ°ĐœĐžŃ‚ŃŒ"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Đ”ĐŸŃŃ‚ŃƒĐżĐ”Đœ ŃĐ»ĐŸĐČарь"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 44eecdc74..4b04075e3 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"KlĂĄvesnica Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Nastavenia klĂĄvesnice Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"MoĆŸnosti zadĂĄvania textu a Ășdajov"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"PrĂ­kazy dennĂ­ka vĂœskumu"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Kontrola pravopisu Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavenia kontroly pravopisu"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"PredvolenĂĄ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"NavrhnĂșĆ„ menĂĄ kontaktov"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"PouĆŸĂ­vaĆ„ menĂĄ z Kontaktov na nĂĄvrhy a opravy"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"PovoliƄ opÀtovné opravy"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"NastaviƄ nåvrhy pre opÀtovné opravy"</string>
<string name="auto_cap" msgid="1719746674854628252">"VeÄŸkĂ© pĂ­smenĂĄ automaticky"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Doplnkové slovníky"</string>
<string name="main_dictionary" msgid="4798763781818361168">"HlavnĂœ slovnĂ­k"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Mierne"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"AgresĂ­vne"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"VeÄŸmi agresĂ­vne"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Návrhy ďalơieho slova"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Na zlepĆĄenie nĂĄvrhov pouĆŸiĆ„ predchĂĄdzajĂșce slovo"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Odhad ďalơieho slova"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"PouĆŸiĆ„ predchĂĄdzajĂșce slovo aj pre predpoveď"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : UloĆŸenĂ©"</string>
<string name="label_go_key" msgid="1635148082137219148">"HÄŸadaĆ„"</string>
<string name="label_next_key" msgid="362972844525672568">"Ďalej"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"HlasovĂœ vstup je zakĂĄzanĂœ"</string>
<string name="configure_input_method" msgid="373356270290742459">"KonfigurovaƄ metódy vstupu"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Jazyky vstupu"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Časová pečiatka denníka"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Časová pečiatka zaznamenaná"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Neukl. relĂĄciu do dennĂ­ka"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Odstraƈ. denníka relåcie"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"DennĂ­k relĂĄcie odstrĂĄnenĂœ"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"DennĂ­k relĂĄcie NIE JE odstr."</string>
<string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"OpĂ€tovnĂœm dotykom uloĆŸĂ­te"</string>
<string name="has_dictionary" msgid="6071847973466625007">"K dispozĂ­cii je slovnĂ­k"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index ce7dc70bb..efcf3bff7 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tipkovnica Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Nastavitve tipkovnice Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"MoĆŸnosti vnosa"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Ukazi za dnevnik raziskav"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Črkovalnik za Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Črkovalnik za Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavitve preverjanja črkovanja"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Privzeto"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Predlagaj imena stikov"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Uporaba imen iz stikov za predloge in popravke"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Omogoči vnovične popravke"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Nastavitev predlogov za vnovične popravke"</string>
<string name="auto_cap" msgid="1719746674854628252">"Samod. velike začetnice"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Dodatni slovarji"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Glavni slovar"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Zmerno"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Strogo"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Zelo strogo"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Predlogi naslednje besede"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Predloge izboljĆĄaj s prejĆĄnjo besedo"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Predvidevanje naslednje besede"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Uporabi prejĆĄnjo besedo tudi za predvidevanje"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: shranjeno"</string>
<string name="label_go_key" msgid="1635148082137219148">"Pojdi"</string>
<string name="label_next_key" msgid="362972844525672568">"Naprej"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. vnos je onem."</string>
<string name="configure_input_method" msgid="373356270290742459">"Nastavitev načinov vnosa"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Jeziki vnosa"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"V dnev. zabeleĆŸi čas. ĆŸig"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Časovni ĆŸig zabeleĆŸen"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Brez dnevnika za to sejo"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Brisanje seje dnevnika"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Dnevnik seje izbrisan"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Dnevnik seje NI izbrisan"</string>
<string name="select_language" msgid="3693815588777926848">"Jeziki vnosa"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotaknite se ĆĄe enkrat, da shranite"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Slovar je na voljo"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 6d2899b47..4cfb77ada 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android тастатура (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ĐŸĐŸĐŽĐ”ŃˆĐ°ĐČања Android Ń‚Đ°ŃŃ‚Đ°Ń‚ŃƒŃ€Đ”"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ĐžĐżŃ†ĐžŃ˜Đ” ŃƒĐœĐŸŃĐ°"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ĐšĐŸĐŒĐ°ĐœĐŽĐ” Đ”ĐČĐžĐŽĐ”ĐœŃ†ĐžŃ˜Đ” ОстражОĐČања"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android ĐżŃ€ĐŸĐČДра праĐČĐŸĐżĐžŃĐ°"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android ĐżŃ€ĐŸĐČДра праĐČĐŸĐżĐžŃĐ° (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ĐŸĐŸĐŽĐ”ŃˆĐ°ĐČања ĐżŃ€ĐŸĐČДрД праĐČĐŸĐżĐžŃĐ°"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ĐŸĐŸĐŽŃ€Đ°Đ·ŃƒĐŒĐ”ĐČĐ°ĐœĐŸ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ĐŸŃ€Đ”ĐŽĐ»ĐŸĐ¶Đž ĐžĐŒĐ”ĐœĐ° ĐșĐŸĐœŃ‚Đ°Đșата"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ĐšĐŸŃ€ĐžŃŃ‚Đž ĐžĐŒĐ”ĐœĐ° Оз ĐšĐŸĐœŃ‚Đ°Đșата за ĐżŃ€Đ”ĐŽĐ»ĐŸĐłĐ” Đž оспраĐČĐșĐ”"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ĐžĐŒĐŸĐłŃƒŃ›Đž ĐżĐŸĐœĐŸĐČĐœĐ” оспраĐČĐșĐ”"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ĐŸĐŸĐŽĐ”ŃˆĐ°ĐČањД ĐżŃ€Đ”ĐŽĐ»ĐŸĐłĐ° за ĐżĐŸĐœĐŸĐČĐœĐ” оспраĐČĐșĐ”"</string>
<string name="auto_cap" msgid="1719746674854628252">"ĐŃƒŃ‚ĐŸĐŒĐ°Ń‚ŃĐșĐž ŃƒĐœĐŸŃ ĐČДлОĐșох ŃĐ»ĐŸĐČа"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ĐŸĐŸĐŒĐŸŃ›ĐœĐž Ń€Đ”Ń‡ĐœĐžŃ†Đž"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ГлаĐČĐœĐž Ń€Đ”Ń‡ĐœĐžĐș"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ĐŁĐŒĐ”Ń€Đ”ĐœĐŸ"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"АгрДсОĐČĐœĐŸ"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Đ’Đ”ĐŸĐŒĐ° агрДсОĐČĐœĐŸ"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"ĐŸŃ€Đ”ĐŽĐ»ĐŸĐ·Đž за ŃĐ»Đ”ĐŽĐ”Ń›Ńƒ рДч"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ĐšĐŸŃ€ĐžŃŃ‚Đž ĐżŃ€Đ”Ń‚Ń…ĐŸĐŽĐœŃƒ рДч за ĐżĐŸĐ±ĐŸŃ™ŃˆĐ°ŃšĐ” ĐżŃ€Đ”ĐŽĐ»ĐŸĐłĐ°"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ĐŸŃ€Đ”ĐŽĐČОђањД слДЎДћД рДчО"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ĐšĐŸŃ€ĐžŃŃ‚Đž ĐżŃ€Đ”Ń‚Ń…ĐŸĐŽĐœŃƒ рДч Đž за прДЎĐČОђањД"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : СачуĐČĐ°ĐœĐŸ"</string>
<string name="label_go_key" msgid="1635148082137219148">"ИЎО"</string>
<string name="label_next_key" msgid="362972844525672568">"ХлДЎДћД"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Đ“Đ»Đ°ŃĐŸĐČĐœĐž ŃƒĐœĐŸŃ јД ĐŸĐœĐ”ĐŒĐŸĐłŃƒŃ›Đ”Đœ"</string>
<string name="configure_input_method" msgid="373356270290742459">"ĐšĐŸĐœŃ„ĐžĐłŃƒŃ€ĐžŃĐ°ŃšĐ” ĐŒĐ”Ń‚ĐŸĐŽĐ° ŃƒĐœĐŸŃĐ°"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ĐˆĐ”Đ·ĐžŃ†Đž за ŃƒĐœĐŸŃ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"НаĐČДЎО ĐČŃ€Đ”ĐŒĐ”ĐœŃĐșу ĐŸĐ·ĐœĐ°Đșу у Đ”ĐČĐžĐŽĐ”ĐœŃ†ĐžŃ˜Đž"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ĐĄĐœĐžĐŒŃ™Đ”ĐœĐ° ĐČŃ€Đ”ĐŒĐ”ĐœŃĐșа ĐŸĐ·ĐœĐ°Đșа"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ĐĐ” Đ”ĐČĐžĐŽĐ”ĐœŃ‚ĐžŃ€Đ°Ń˜ ĐŸĐČу сДсОју"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"БрОсањД Đ”ĐČĐžĐŽĐ”ĐœŃ†ĐžŃ˜Đ” сДсОјД"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ЕĐČĐžĐŽĐ”ĐœŃ†ĐžŃ˜Đ° сДсОјД јД ĐŸĐ±Ń€ĐžŃĐ°ĐœĐ°"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"ЕĐČĐžĐŽĐ”ĐœŃ†ĐžŃ˜Đ° сДсОјД НИЈЕ ĐžĐ·Đ±Ń€ĐžŃĐ°ĐœĐ°"</string>
<string name="select_language" msgid="3693815588777926848">"ĐˆĐ”Đ·ĐžŃ†Đž ŃƒĐœĐŸŃĐ°"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ĐŸĐŸĐœĐŸĐČĐŸ ĐŽĐŸĐŽĐžŃ€ĐœĐžŃ‚Đ” Ўа бОстД сачуĐČалО"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Đ Đ”Ń‡ĐœĐžĐș јД ĐŽĐŸŃŃ‚ŃƒĐżĐ°Đœ"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 75e80d42d..f24446976 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androids tangentbord (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"InstÀllningar för Androids tangentbord"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Inmatningsalternativ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Loggkommandon"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Stavningskontroll i Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Stavningskontroll i Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"InstÀllningar för stavningskontroll"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"FöreslÄ kontaktnamn"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"AnvÀnd namn frÄn Kontakter för förslag och korrigeringar"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Aktivera omkorrigeringar"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"StÀll in förslag för omkorrigeringar"</string>
<string name="auto_cap" msgid="1719746674854628252">"Automatiska versaler"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"TillÀggsordlistor"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Huvudordlistan"</string>
@@ -61,10 +60,8 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"MÄttlig"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Aggressiv"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Mycket aggressivt"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"FöreslÄ nÀsta ord"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"FörbÀttra förslagen med föregÄende ord"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"FörutspÄ nÀsta ord"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"AnvÀnd Àven föregÄende ord för att ge förslag"</string>
+ <string name="bigram_prediction" msgid="5809665643352206540">"FöreslÄ nÀsta ord"</string>
+ <string name="bigram_prediction_summary" msgid="3253961591626441019">"Baserat pÄ föregÄende ord"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: sparat"</string>
<string name="label_go_key" msgid="1635148082137219148">"Kör"</string>
<string name="label_next_key" msgid="362972844525672568">"NĂ€sta"</string>
@@ -111,6 +108,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Röstinmatning inaktiv"</string>
<string name="configure_input_method" msgid="373356270290742459">"Konfigurera inmatningsmetoder"</string>
<string name="language_selection_title" msgid="1651299598555326750">"InmatningssprÄk"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Markera tidpunkt i loggen"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Tidpunkten har sparats"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Logga inte detta besök"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Besöksloggen tas bort"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Besöksloggen togs bort"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Besöksloggen togs EJ bort"</string>
<string name="select_language" msgid="3693815588777926848">"InmatningssprÄk"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Spara genom att trycka igen"</string>
<string name="has_dictionary" msgid="6071847973466625007">"En ordlista Àr tillgÀnglig"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index da51cb3b9..4b60868c2 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Kicharazio cha Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Mipangilio ya kibodi ya Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Amri za Kumbukumbu za Utafiti"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Kikagua tahajia cha Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kikagua tahajia cha Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Mipangilio ya kukagua sarufi"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Chaguo-msingi"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Pendekeza majini ya Anwani"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Tumia majina kutoka kwa Anwani kwa mapendekezo na marekebisho"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Wezesha masahihisho mapya"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Weka mapendekezo kwa ajili ya kusahihisha upya"</string>
<string name="auto_cap" msgid="1719746674854628252">"Uwekaji wa herufi kubwa kiotomatiki"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Nyongeza za kamusi"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Kamusi kuu"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Ya wastani"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Ya hima"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Changamfu zaidi"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Mapendekezo ya neno lifuatalo"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Tumia neno la awali ili kuboresha mapendekezo"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Utabiri wa neno lifuatalo"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Tumia neno la awali pia kwa udadisi"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Imehifadhiwa"</string>
<string name="label_go_key" msgid="1635148082137219148">"Nenda"</string>
<string name="label_next_key" msgid="362972844525672568">"Ifuatayo"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Uingizaji sauti umelemazwa"</string>
<string name="configure_input_method" msgid="373356270290742459">"Sanidi mbinu za uingizaji"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Lugha za uingizaji"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Dokeza mhuri wa muda kwenye kumbukumbu"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Mhuri wa muda uliorekodiwa"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Usihifadhi kumbukumbu za kipindi hiki"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Inafuta kumbukumbu za kipindi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Kumbukumbu za kipindi zimefutwa"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Kumbukumbu za kipindi HAZIJAFUTWA"</string>
<string name="select_language" msgid="3693815588777926848">"Lugha zinazoruhusiwa"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Gusa tena ili kuhifadhi"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Kamusi inapatikana"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index da20d6607..b5ba7abe8 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"àžàžČàžŁàž•àž±àč‰àž‡àž„àčˆàžČàčàž›àč‰àž™àžžàžŽàžĄàžžàčŒ Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"àž•àž±àž§àč€àž„àž·àž­àžàžàžČàžŁàž›àč‰àž­àž™àž‚àč‰àž­àžĄàžčàž„"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"àž„àžłàžȘàž±àčˆàž‡àžšàž±àž™àž—àž¶àžàžàžČàžŁàž§àžŽàžˆàž±àžą"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"àčàž­àž™àž”àžŁàž­àžąàž”àčŒàž•àžŁàž§àžˆàžȘàž­àžšàžàžČàžŁàžȘàž°àžàž”"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"àčàž­àž™àž”àžŁàž­àžąàž”àčŒàž•àžŁàž§àžˆàžȘàž­àžšàžàžČàžŁàžȘàž°àžàž” (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"àžàžČàžŁàž•àž±àč‰àž‡àž„àčˆàžČàžàžČàžŁàž•àžŁàž§àžˆàžȘàž­àžšàžàžČàžŁàžȘàž°àžàž”"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"àž„àčˆàžČàč€àžŁàžŽàčˆàžĄàž•àč‰àž™"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"àčàž™àž°àž™àžłàžŠàž·àčˆàž­àžœàžčàč‰àž•àžŽàž”àž•àčˆàž­"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"àčƒàžŠàč‰àžŠàž·àčˆàž­àžˆàžČàžàžŁàžČàžąàžŠàž·àčˆàž­àž•àžŽàž”àž•àčˆàž­àžȘàžłàž«àžŁàž±àžšàž„àžłàčàž™àž°àž™àžłàčàž„àž°àžàžČàžŁàčàžàč‰àč„àž‚"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"àč€àž›àžŽàž”àčƒàžŠàč‰àž‡àžČàž™àžàžČàžŁàčàžàč‰àč„àž‚àž‹àč‰àžł"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"àž•àž±àč‰àž‡àž„àčˆàžČàž„àžłàčàž™àž°àž™àžłàžȘàžłàž«àžŁàž±àžšàžàžČàžŁàčàžàč‰àč„àž‚àž‹àč‰àžł"</string>
<string name="auto_cap" msgid="1719746674854628252">"àž›àžŁàž±àžšàč€àž›àč‡àž™àž•àž±àž§àžžàžŽàžĄàžžàčŒàčƒàž«àžàčˆàž­àž±àž•àč‚àž™àžĄàž±àž•àžŽ"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"àžžàžˆàž™àžČàž™àžžàžàžŁàžĄ Add-On"</string>
<string name="main_dictionary" msgid="4798763781818361168">"àžžàžˆàž™àžČàž™àžžàžàžŁàžĄàž«àž„àž±àž"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"àž›àžČàž™àžàž„àžČàž‡"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"àč€àž‚àč‰àžĄàž‡àž§àž”"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"àč€àž‚àč‰àžĄàž‡àž§àž”àžĄàžČàž"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"àž„àžłàčàž™àž°àž™àžłàžȘàžłàž«àžŁàž±àžšàž„àžłàž–àž±àž”àč„àž›"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"àčƒàžŠàč‰àž„àžłàžàčˆàž­àž™àž«àž™àč‰àžČàž™àž”àč‰àč€àžžàž·àčˆàž­àž›àžŁàž±àžšàž›àžŁàžžàž‡àž„àžłàčàž™àž°àž™àžł"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"àžàžČàžŁàž„àžČàž”àž„àž°àč€àž™àž„àžłàž–àž±àž”àč„àž›"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"àčƒàžŠàč‰àž„àžłàžàčˆàž­àž™àž«àž™àč‰àžČàž™àž”àč‰àžȘàžłàž«àžŁàž±àžšàžàžČàžŁàž„àžČàž”àž„àž°àč€àž™"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : àžšàž±àž™àž—àž¶àžàčàž„àč‰àž§"</string>
<string name="label_go_key" msgid="1635148082137219148">"àč„àž›"</string>
<string name="label_next_key" msgid="362972844525672568">"àž–àž±àž”àč„àž›"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"àž›àžŽàž”àčƒàžŠàč‰àž‡àžČàž™àž›àč‰àž­àž™àž‚àč‰àž­àžĄàžčàž„àž”àč‰àž§àžąàč€àžȘàž”àžąàž‡"</string>
<string name="configure_input_method" msgid="373356270290742459">"àžàžłàž«àž™àž”àž„àčˆàžČàž§àžŽàž˜àž”àžàžČàžŁàž›àč‰àž­àž™àž‚àč‰àž­àžĄàžčàž„"</string>
<string name="language_selection_title" msgid="1651299598555326750">"àž àžČàž©àžČàčƒàž™àžàžČàžŁàž›àč‰àž­àž™àž‚àč‰àž­àžĄàžčàž„"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"àžˆàž”àč€àž§àž„àžČàžšàž±àž™àž—àž¶àžàč„àž§àč‰àčƒàž™àžšàž±àž™àž—àž¶àž"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"àžšàž±àž™àž—àž¶àžàč€àž§àž„àžČàžšàž±àž™àž—àž¶àžàčàž„àč‰àž§"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"àž­àžąàčˆàžČàžšàž±àž™àž—àž¶àžàč€àž‹àžȘàžŠàž±àž™àž™àž”àč‰"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"àžàžłàž„àž±àž‡àž„àžšàžšàž±àž™àž—àž¶àžàč€àž‹àžȘàžŠàž±àž™"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"àž„àžšàžšàž±àž™àž—àž¶àžàč€àž‹àžȘàžŠàž±àž™àčàž„àč‰àž§"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"àžšàž±àž™àž—àž¶àžàč€àž‹àžȘàžŠàž±àž™àč„àžĄàčˆàž–àžčàžàž„àžš"</string>
<string name="select_language" msgid="3693815588777926848">"àž àžČàž©àžČàžȘàžłàž«àžŁàž±àžšàžàžČàžŁàž›àč‰àž­àž™àž‚àč‰àž­àžĄàžčàž„"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"àčàž•àž°àž­àž”àžàž„àžŁàž±àč‰àž‡àč€àžžàž·àčˆàž­àžšàž±àž™â€‹â€‹àž—àž¶àž"</string>
<string name="has_dictionary" msgid="6071847973466625007">"àžĄàž”àžžàžˆàž™àžČàž™àžžàžàžŁàžĄàčƒàž«àč‰àčƒàžŠàč‰àž‡àžČàž™"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index 7d365b2dc..60b4762d8 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Mga setting ng Android keyboard"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Mga pagpipilian sa input"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Cmmnd sa Log ng Pnnliksik"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Pang-check ng pagbabaybay ng Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pang-check ng pagbabaybay ng Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Mga setting ng pang-check ng pagbabaybay"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Mungkahi pangalan Contact"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Gamitin pangalan mula Mga Contact sa mga mungkahi\'t pagwawasto"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Paganahin ang mga muling pagtatama"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Magtakda ng mga suhestyon para sa mga muling pagtatama"</string>
<string name="auto_cap" msgid="1719746674854628252">"Auto-capitalization"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Mga diksyunaryo na add-on"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Pangunahing diksyunaryo"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresibo"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Napaka-agresibo"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Mga paghuhula sa susunod na salita"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Gamitin ang naunang salita para mapahusay ang mga suhestiyon"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Paghuhula sa susunod na salita"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Gamitin ang nakaraang salita para din sa hula"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Na-save"</string>
<string name="label_go_key" msgid="1635148082137219148">"Punta"</string>
<string name="label_next_key" msgid="362972844525672568">"Susunod"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hindi pinagana ang voice input"</string>
<string name="configure_input_method" msgid="373356270290742459">"I-configure ang mga pamamaraan ng pag-input"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Mag-input ng mga wika"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Tandaan timestamp sa log"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Na-record na timestamp"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Huwag i-log ang session"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Tinatanggl log ng session"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Tinanggal log ng session"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"HND ntnggl log ng session"</string>
<string name="select_language" msgid="3693815588777926848">"Mga wika ng input"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Pinduting muli upang i-save"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Available ang diksyunaryo"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index b2f73912e..2567c6677 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android klavye (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android klavye ayarları"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"GiriƟ seçenekleri"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Araßtırma GĂŒnlĂŒÄŸĂŒ Komutları"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android yazım denetleyici"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android yazım denetleyici (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Yazım denetimi ayarları"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Varsayılan"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Kißi Adları öner"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Öneri ve dĂŒzeltmeler için Kißiler\'deki adları kullan"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"DĂŒzeltmeleri etkinleßtir"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Yeniden dĂŒzeltmeler için önerileri ayarla"</string>
<string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak bĂŒyĂŒk fark yap"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Ek sözlĂŒkler"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Ana sözlĂŒk"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ÖlĂ§ĂŒlĂŒ"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresif"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Çok geniß ölçekte"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Sonraki kelime önerileri"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Önerileri gelißtirmek için önceki kelimeyi kullan"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Sonraki kelime tahmini"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Önceki kelimeyi de tahmin için kullan"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kaydedildi"</string>
<string name="label_go_key" msgid="1635148082137219148">"Git"</string>
<string name="label_next_key" msgid="362972844525672568">"İleri"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Sesle grß devre dıßı"</string>
<string name="configure_input_method" msgid="373356270290742459">"Giriß yöntemlerini yapılandır"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Giriß dilleri"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"GĂŒnlĂŒÄŸe zaman damgası koy"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Zaman damgası kaydedildi"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Bu oturumu gĂŒnlĂŒÄŸe kaydetme"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Oturum gĂŒnlĂŒÄŸĂŒ siliniyor"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Oturum gĂŒnlĂŒÄŸĂŒ silindi"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Oturum gĂŒnlĂŒÄŸĂŒ SİLİNMEDİ"</string>
<string name="select_language" msgid="3693815588777926848">"Giriß dilleri"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Kaydetmek için tekrar dokunun"</string>
<string name="has_dictionary" msgid="6071847973466625007">"SözlĂŒk kullanılabilir"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index e994e1a15..3fc8402ba 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"КлаĐČіатура Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"ĐĐ°Đ»Đ°ŃˆŃ‚-ĐœŃ ĐșлаĐČіат. Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"ĐŸĐ°Ń€Đ°ĐŒ. ĐČĐČĐ”ĐŽĐ”ĐœĐœŃ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ĐšĐŸĐŒĐ°ĐœĐŽĐž Đ¶ŃƒŃ€ĐœĐ°Đ»Ńƒ ĐŽĐŸŃĐ»Ń–ĐŽĐ¶."</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Засіб пДрДĐČірĐșĐž ĐŸŃ€Ń„ĐŸĐłŃ€Đ°Ń„Ń–Ń— Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Засіб пДрДĐČірĐșĐž ĐŸŃ€Ń„ĐŸĐłŃ€Đ°Ń„Ń–Ń— Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"ĐĐ°Đ»Đ°ŃˆŃ‚ŃƒĐČĐ°ĐœĐœŃ пДрДĐČірĐșĐž ĐŸŃ€Ń„ĐŸĐłŃ€Đ°Ń„Ń–Ń—"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"За ŃƒĐŒĐŸĐČŃ‡Đ°ĐœĐœŃĐŒ"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ĐŸŃ€ĐŸĐżĐŸĐœ. Ń–ĐŒĐ”ĐœĐ° ĐșĐŸĐœŃ‚Đ°ĐșтіĐČ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"ВоĐșĐŸŃ€ĐžŃŃ‚. Ń–ĐŒĐ”ĐœĐ° Đ·Ń– спОсĐșу ĐșĐŸĐœŃ‚Đ°ĐșтіĐČ ĐŽĐ»Ń ĐżŃ€ĐŸĐżĐŸĐ·ĐžŃ†Ń–Đč і ĐČопраĐČĐ»Đ”ĐœŃŒ"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ĐŁĐČŃ–ĐŒĐșĐœŃƒŃ‚Đž ĐČопраĐČĐ»Đ”ĐœĐœŃ"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"ĐŸĐŸĐșазуĐČато ĐČĐ°Ń€Ń–Đ°ĐœŃ‚Đž аĐČŃ‚ĐŸĐČопраĐČĐ»Đ”ĐœŃŒ"</string>
<string name="auto_cap" msgid="1719746674854628252">"АĐČŃ‚ĐŸ ĐČĐžĐșĐŸŃ€. ĐČДл. літДр"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Đ”ĐŸĐŽĐ°ĐœŃ– ŃĐ»ĐŸĐČĐœĐžĐșĐž"</string>
<string name="main_dictionary" msgid="4798763781818361168">"ĐžŃĐœĐŸĐČĐœĐžĐč ŃĐ»ĐŸĐČĐœĐžĐș"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ĐŸĐŸĐŒŃ–Ń€ĐœĐ”"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"АĐșтоĐČĐœĐ”"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Đ”ŃƒĐ¶Đ” аĐșтоĐČĐœĐ”"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"ĐŸŃ€ĐŸĐżĐŸĐ·ĐžŃ†Ń–Ń— ĐœĐ°ŃŃ‚ŃƒĐżĐœĐŸĐłĐŸ ŃĐ»ĐŸĐČа"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"ВоĐșĐŸŃ€ĐžŃŃ‚Đ°Ń‚Đž ĐżĐŸĐżĐ”Ń€Đ”ĐŽĐœŃ” ŃĐ»ĐŸĐČĐŸ ĐŽĐ»Ń ĐżĐŸĐșŃ€Đ°Ń‰Đ”ĐœĐœŃ ĐżŃ€ĐŸĐżĐŸĐ·ĐžŃ†Ń–Đč"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"ĐŸĐ”Ń€Đ”ĐŽĐ±Đ°Ń‡Đ”ĐœĐœŃ ĐœĐ°ŃŃ‚ŃƒĐżĐœĐŸĐłĐŸ ŃĐ»ĐŸĐČа"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ВоĐșĐŸŃ€ĐžŃŃ‚ĐŸĐČуĐČато ĐżĐŸĐżĐ”Ń€Đ”ĐŽĐœŃ” ŃĐ»ĐŸĐČĐŸ таĐșĐŸĐ¶ яĐș ĐżĐ”Ń€Đ”ĐŽĐ±Đ°Ń‡Đ”ĐœĐžĐč запОт"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Đ·Đ±Đ”Ń€Đ”Đ¶Đ”ĐœĐŸ"</string>
<string name="label_go_key" msgid="1635148082137219148">"Іто"</string>
<string name="label_next_key" msgid="362972844525672568">"Далі"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Đ“ĐŸĐ»ĐŸŃ. ĐČĐČіЮ ĐČĐžĐŒĐșĐœĐ”ĐœĐŸ"</string>
<string name="configure_input_method" msgid="373356270290742459">"ĐĐ°Đ»Đ°ŃˆŃ‚ŃƒĐČĐ°ĐœĐœŃ ĐŒĐ”Ń‚ĐŸĐŽŃ–ĐČ ĐČĐČĐ”ĐŽĐ”ĐœĐœŃ"</string>
<string name="language_selection_title" msgid="1651299598555326750">"ĐœĐŸĐČĐž ĐČĐČĐŸĐŽŃƒ"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"МітĐșа часу ĐČ Đ¶ŃƒŃ€ĐœĐ°Đ»Ń–"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Đ—Đ°ĐżĐžŃĐ°ĐœĐ° ĐŒŃ–Ń‚Đșа часу"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"ĐĐ” Ń€Đ”Ń”ŃŃ‚Ń€ŃƒĐČато цю сДсію"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Đ’ĐžĐŽĐ°Đ»Đ”ĐœĐœŃ Đ¶ŃƒŃ€ĐœĐ°Đ»Ńƒ сДсії"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Đ–ŃƒŃ€ĐœĐ°Đ» сДсії ĐČĐžĐŽĐ°Đ»Đ”ĐœĐŸ"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Đ–ŃƒŃ€ĐœĐ°Đ» сДсії НЕ ĐČĐžĐŽĐ°Đ»Đ”ĐœĐŸ"</string>
<string name="select_language" msgid="3693815588777926848">"ĐœĐŸĐČĐž ĐČĐČĐ”ĐŽĐ”ĐœĐœŃ"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ĐąĐŸŃ€ĐșĐœŃ–Ń‚ŃŒŃŃ Đ·ĐœĐŸĐČу, Ń‰ĐŸĐ± збДрДгтО"</string>
<string name="has_dictionary" msgid="6071847973466625007">"ĐĄĐ»ĐŸĐČĐœĐžĐș ĐŽĐŸŃŃ‚ŃƒĐżĐœĐžĐč"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 753af1840..57c1bdbb4 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"BĂ n phĂ­m Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"CĂ i đáș·t bĂ n phĂ­m Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"TĂčy chọn nháș­p"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Lệnh ghi nháș­t kĂœ cho nghiĂȘn cứu"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"TrĂŹnh kiểm tra chĂ­nh táșŁ Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"TrĂŹnh kiểm tra chĂ­nh táșŁ Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"CĂ i đáș·t kiểm tra chĂ­nh táșŁ"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Máș·c định"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Đề xuáș„t tĂȘn liĂȘn hệ"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Sá»­ dỄng tĂȘn từ Danh báșĄ cho cĂĄc đề xuáș„t vĂ  chỉnh sá»­a"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Báș­t sá»­a đổi láșĄi"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Đáș·t đề xuáș„t cho cĂĄc sá»­a đổi láșĄi"</string>
<string name="auto_cap" msgid="1719746674854628252">"Tá»± động viáșżt hoa"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ThĂȘm từ điển"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Từ điển chĂ­nh"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ÄÆĄn giáșŁn"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Linh hoáșĄt"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Ráș„t linh hoáșĄt"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Đề xuáș„t từ tiáșżp theo"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Sá»­ dỄng từ trước đó để cáșŁi tiáșżn đề xuáș„t"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Dá»± đoĂĄn từ tiáșżp theo"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"CĆ©ng sá»­ dỄng từ trước đó để dá»± đoĂĄn"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Đã lưu"</string>
<string name="label_go_key" msgid="1635148082137219148">"TĂŹm"</string>
<string name="label_next_key" msgid="362972844525672568">"Tiáșżp theo"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Nháș­p liệu báș±ng giọng nĂłi đã bị táșŻt"</string>
<string name="configure_input_method" msgid="373356270290742459">"Định cáș„u hĂŹnh phÆ°ÆĄng thức nháș­p"</string>
<string name="language_selection_title" msgid="1651299598555326750">"NgĂŽn ngữ nháș­p"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Dáș„u thời gian ghi chĂș trong nháș­t kĂœ"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Dáș„u thời gian đã ghi"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"KhĂŽng ghi nháș­t kĂœ phiĂȘn nĂ y"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Đang xĂła nháș­t kĂœ phiĂȘn"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Đã xĂła nháș­t kĂœ phiĂȘn"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Nháș­t kĂœ phiĂȘn KHÔNG bị xĂła"</string>
<string name="select_language" msgid="3693815588777926848">"NgĂŽn ngữ nháș­p"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"CháșĄm láșĄi để lưu"</string>
<string name="has_dictionary" msgid="6071847973466625007">"CĂł sáș”n từ điển"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index efde54103..deb4fe0fc 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 锼盘 (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android é”źç›˜èźŸçœź"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"èŸ“ć…„é€‰éĄč"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ç ”ç©¶èź°ćœ•ć‘œä»€"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android æ‹Œć†™æŁ€æŸ„ć·„ć…·"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android æ‹Œć†™æŁ€æŸ„ć·„ć…· (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"æ‹Œć†™æŁ€æŸ„èźŸçœź"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"é»˜èź€"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"è”çł»äșș槓損ć»șèźź"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"äœżç”šè”çł»äșșäž­çš„ć§“ćæäŸ›ć»șèźźć’Œæ›Žæ­Ł"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ć…èźžć†æŹĄæ›Žæ­Ł"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"èźŸçœźć»șèźźä»„ç”šäșŽć†æŹĄæ›Žæ­Ł"</string>
<string name="auto_cap" msgid="1719746674854628252">"è‡Ș抚性憙"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"é™„ćŠ èŻć…ž"</string>
<string name="main_dictionary" msgid="4798763781818361168">"äž»èŻć…ž"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"氏æ”č"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"性æ”č"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"æ”čćŠšæžć€§"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"äž‹äž€ć­—èŻć»șèźź"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"äœżç”šäžŠäž€ć­—èŻæ”čèż›ć»șèźź"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"äž‹äž€ć­—èŻéą„æ”‹"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ç»“ćˆć‰äž€äžȘć­—èŻèż›èĄŒéą„æ”‹"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>ć·Č保歘"</string>
<string name="label_go_key" msgid="1635148082137219148">"ćŒ€ć§‹"</string>
<string name="label_next_key" msgid="362972844525672568">"䞋䞀歄"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"èŻ­éŸłèŸ“ć…„ćŠŸèƒœć·Č恜甹"</string>
<string name="configure_input_method" msgid="373356270290742459">"é…çœźèŸ“ć…„æł•"</string>
<string name="language_selection_title" msgid="1651299598555326750">"èŸ“ć…„èŻ­èš€"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"æ ‡èź°èź°ćœ•äž­çš„æ—¶é—Ž"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ć·Čæ ‡èź°æ—¶é—Ž"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"äžèź°ćœ•æœŹæŹĄäŒšèŻ"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"æ­Łćœšćˆ é™€äŒšèŻèź°ćœ•"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"äŒšèŻèź°ćœ•ć·Čćˆ é™€"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"æœȘèƒœćˆ é™€äŒšèŻèź°ćœ•"</string>
<string name="select_language" msgid="3693815588777926848">"èŸ“ć…„èŻ­èš€"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ć†æŹĄè§Šæ‘žćłćŻäżć­˜"</string>
<string name="has_dictionary" msgid="6071847973466625007">"æœ‰ćŻç”šèŻć…ž"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index 51df022aa..bbe6976dc 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 鍔盀 (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Android é”ç›€èš­ćźš"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"èŒžć…„éžé …"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"研究玀錄指什"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Android æ‹Œć­—æȘ࿟„"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android æ‹Œć­—æȘ࿟„ (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"æ‹Œć­—æȘ࿟„èš­ćźš"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"預蚭"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"ć»șè­°èŻç”Ąäșșćçš±"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"æ čæ“šă€ŒèŻç”Ąäșșă€ćçš±æäŸ›ć»șè­°èˆ‡äżźæ­Ł"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"ć•Ÿç”šé‡æ–°æ›Žæ­Ł"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"èš­ćźšć»șè­°äŸ›é‡æ–°æ›Žæ­Ł"</string>
<string name="auto_cap" msgid="1719746674854628252">"è‡Ș拕性毫"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"ć€–æŽ›ć­—ć…ž"</string>
<string name="main_dictionary" msgid="4798763781818361168">"äž»èŠć­—ć…ž"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"æ›Žæ­ŁçŻ„ćœć°"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"æ›Žæ­ŁçŻ„ćœć€§"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"æ›Žæ­ŁçŻ„ćœæ„”ć€§"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"äž‹äž€ć€‹ć­—è©žć»șè­°"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"æ čæ“šć‰äž€ć€‹ć­—è©žæ‰Ÿć‡șæ›Žé©ćˆçš„ć»șè­°"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"äž‹äž€ć€‹ć­—è©žé æžŹ"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"ćŒæšŁäœżç”šć‰äž€ć€‹ć­—è©žé€ČèĄŒé æžŹ"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>ć·Čć„Č歘"</string>
<string name="label_go_key" msgid="1635148082137219148">"開構"</string>
<string name="label_next_key" msgid="362972844525672568">"çčŒçșŒ"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"èȘžéŸłèŒžć…„ć·Č恜甹"</string>
<string name="configure_input_method" msgid="373356270290742459">"èš­ćźšèŒžć…„æł•"</string>
<string name="language_selection_title" msgid="1651299598555326750">"èŒžć…„èȘžèš€"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"ćœšçŽ€éŒ„äž­ćŠ èš»æ™‚é–“æˆłèš˜"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"ć·Čèš˜éŒ„æ™‚é–“æˆłèš˜"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"äžèŠèš˜éŒ„é€™ć€‹ć·„äœœéšŽæź”"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"æ­ŁćœšćˆȘé™€ć·„äœœéšŽæź”çŽ€éŒ„"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"ć·ČćˆȘé™€ć·„äœœéšŽæź”çŽ€éŒ„"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"「æœȘ」ćˆȘé™€ć·„äœœéšŽæź”çŽ€éŒ„"</string>
<string name="select_language" msgid="3693815588777926848">"èŒžć…„èȘžèš€"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"ć†æŹĄèŒ•è§žćłćŻć„Č歘"</string>
<string name="has_dictionary" msgid="6071847973466625007">"ćŻäœżç”šć­—ć…ž"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index d3f80e42a..101d91498 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -24,6 +24,7 @@
<string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Ikhibhodi ye-Android (AOSP)"</string>
<string name="english_ime_settings" msgid="6661589557206947774">"Izilungiselelo zekhibhodi ye-Android"</string>
<string name="english_ime_input_options" msgid="3909945612939668554">"Okukhethwa kukho kokungenayo"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Imiyalo yefayela lokungena lokucwaninga"</string>
<string name="spell_checker_service_name" msgid="7338064335159755926">"Isihloli sokupela se-Android"</string>
<string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Isihloli sokupela se-Android (AOSP)"</string>
<string name="android_spell_checker_settings" msgid="5822324635435443689">"Izilungiselelo zokuhlola ukupela"</string>
@@ -45,8 +46,6 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Okuzenzakalelayo"</string>
<string name="use_contacts_dict" msgid="4435317977804180815">"Sikisela amagama Othintana nabo"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"Amagama abasebenzisi kusuka Kothintana nabo bokusikisela nokulungisa"</string>
- <string name="enable_span_insert" msgid="7204653105667167620">"Vumela ukulungiswa kabusha"</string>
- <string name="enable_span_insert_summary" msgid="2947317657871394467">"Setha iziphakamiso zokulungisa kabusha"</string>
<string name="auto_cap" msgid="1719746674854628252">"Ukwenza ofeleba okuzenzakalelayo"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"Faka izichazamazwi"</string>
<string name="main_dictionary" msgid="4798763781818361168">"Isichazamazwi sakho ngqangi"</string>
@@ -61,10 +60,10 @@
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Thobekile"</string>
<string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Bukhali"</string>
<string name="auto_correction_threshold_mode_very_aggeressive" msgid="3386782235540547678">"Nobudlova kakhulu"</string>
- <string name="bigram_suggestion" msgid="8169311444438922902">"Iziphakamiso zegama elilandelayo"</string>
- <string name="bigram_suggestion_summary" msgid="6635527607242625713">"Sebenzisa igama elandulele ukuthuthukisa iziphakamiso"</string>
- <string name="bigram_prediction" msgid="3216364899483135294">"Ukuqagela kwegama elilandelayo"</string>
- <string name="bigram_prediction_summary" msgid="1747261921174300098">"Sebenzisa igama langaphambilini ukuze uqagele"</string>
+ <!-- no translation found for bigram_prediction (5809665643352206540) -->
+ <skip />
+ <!-- no translation found for bigram_prediction_summary (3253961591626441019) -->
+ <skip />
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kulondoloziwe"</string>
<string name="label_go_key" msgid="1635148082137219148">"Iya"</string>
<string name="label_next_key" msgid="362972844525672568">"Okulandelayo"</string>
@@ -111,6 +110,12 @@
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Okufakwayo ngezwi kuvinjelwe"</string>
<string name="configure_input_method" msgid="373356270290742459">"Misa izindlela zokufakwayo"</string>
<string name="language_selection_title" msgid="1651299598555326750">"Izilimi zokufakwayo"</string>
+ <string name="note_timestamp_for_researchlog" msgid="1889446857977976026">"Qaphela isitembu sesikhathi efayeleni lokungena"</string>
+ <string name="notify_recorded_timestamp" msgid="8036429032449612051">"Isitembu sesikhathi esirekhodiwe"</string>
+ <string name="do_not_log_this_session" msgid="413762473641146336">"Ungenzi ifayela lokungena lalesi sikhathi"</string>
+ <string name="notify_session_log_deleting" msgid="3299507647764414623">"Isusa ifayela lokungena lesikhathi"</string>
+ <string name="notify_session_log_deleted" msgid="8687927130100934686">"Ifayela lokungena lesikhathi lisusiwe"</string>
+ <string name="notify_session_log_not_deleted" msgid="2592908998810755970">"Ifayela lokungena lesikhathi alisusiwe"</string>
<string name="select_language" msgid="3693815588777926848">"Izilimi zokufakwayo"</string>
<string name="hint_add_to_dictionary" msgid="573678656946085380">"Thinta futhi ukuze ulondoloze"</string>
<string name="has_dictionary" msgid="6071847973466625007">"Isichazamazwi siyatholakala"</string>
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 8d3319dae..589830d8e 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -22,13 +22,10 @@
<bool name="config_use_fullscreen_mode">false</bool>
<bool name="config_enable_show_voice_key_option">true</bool>
<bool name="config_enable_show_popup_on_keypress_option">true</bool>
- <bool name="config_enable_next_word_suggestions_option">true</bool>
- <bool name="config_enable_usability_study_mode_option">false</bool>
+ <!-- TODO: Disable the following configuration for production. -->
+ <bool name="config_enable_usability_study_mode_option">true</bool>
<!-- Whether or not Popup on key press is enabled by default -->
<bool name="config_default_popup_preview">true</bool>
- <!-- Default value for next word suggestion: while showing suggestions for a word should we weigh
- in the previous word? -->
- <bool name="config_default_next_word_suggestions">true</bool>
<!-- Default value for next word prediction: after entering a word and a space only, should we look
at input history to suggest a hopefully helpful suggestions for the next word? -->
<bool name="config_default_next_word_prediction">true</bool>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index d51d3789a..6c66a4844 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -26,6 +26,8 @@
<string name="english_ime_settings">Android keyboard settings</string>
<!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] -->
<string name="english_ime_input_options">Input options</string>
+ <!-- Title for Latin keyboard research log dialog, which contains special commands for users that contribute data for research. [CHAR LIMIT=33] -->
+ <string name="english_ime_research_log">Research Log Commands</string>
<!-- Name of Android spell checker service -->
<string name="spell_checker_service_name">Android spell checker</string>
@@ -83,11 +85,6 @@
<!-- Description for option enabling or disabling the use of names of people in Contacts for suggestion and correction [CHAR LIMIT=65] -->
<string name="use_contacts_dict_summary">Use names from Contacts for suggestions and corrections</string>
- <!-- Option name for enabling insertion of suggestion spans (advanced option) [CHAR LIMIT=25] -->
- <string name="enable_span_insert">Enable recorrections</string>
- <!-- Option summary for enabling insertion of suggestion spans (advanced option) [CHAR LIMIT=65] -->
- <string name="enable_span_insert_summary">Set suggestions for recorrections</string>
-
<!-- Option to enable auto capitalization of sentences -->
<string name="auto_cap">Auto-capitalization</string>
@@ -118,14 +115,10 @@
<!-- Option to suggest auto correction suggestions very aggressively. Auto-corrects to a word which has even large edit distance from typed word. [CHAR LIMIT=20] -->
<string name="auto_correction_threshold_mode_very_aggeressive">Very aggressive</string>
- <!-- Option to enable next word correction -->
- <string name="bigram_suggestion">Next word suggestions</string>
- <!-- Option to enable next word suggestion. This uses the previous word in an attempt to improve the suggestions quality -->
- <string name="bigram_suggestion_summary">Use previous word to improve suggestions</string>
- <!-- Option to enable using next word prediction -->
- <string name="bigram_prediction">Next word prediction</string>
- <!-- Description for "next word prediction" option. This displays suggestions even when there is no input, based on the previous word. -->
- <string name="bigram_prediction_summary">Use previous word also for prediction</string>
+ <!-- Option to enable using next word suggestions. After the user types a space, with this option on, the keyboard will try to predict the next word. -->
+ <string name="bigram_prediction">Next word suggestions</string>
+ <!-- Description for "next word suggestion" option. This displays suggestions even when there is no input, based on the previous word. -->
+ <string name="bigram_prediction_summary">Based on previous word</string>
<!-- Indicates that a word has been added to the dictionary -->
<string name="added_word"><xliff:g id="word">%s</xliff:g> : Saved</string>
@@ -233,6 +226,20 @@
<!-- Title for input language selection screen -->
<string name="language_selection_title">Input languages</string>
+ <!-- Title for dialog option that lets user mark a particular time in the log for later review by experts [CHAR LIMIT=38] -->
+ <string name="note_timestamp_for_researchlog">Note timestamp in log</string>
+ <!-- Toast notification message that the time has been marked for later review. [CHAR LIMIT=25] -->
+ <string name="notify_recorded_timestamp">Recorded timestamp</string>
+
+ <!-- Title for dialog option to let users cancel logging and delete log for this session [CHAR LIMIT=35] -->
+ <string name="do_not_log_this_session">Do not log this session</string>
+ <!-- Toast notification that the system is processing the request to delete the log for this session [CHAR LIMIT=35] -->
+ <string name="notify_session_log_deleting">Deleting session log</string>
+ <!-- Toast notification that the system has successfully deleted the log for this session [CHAR LIMIT=35] -->
+ <string name="notify_session_log_deleted">Session log deleted</string>
+ <!-- Toast notification that the system has failed to delete the log for this session [CHAR LIMIT=35] -->
+ <string name="notify_session_log_not_deleted">Session log NOT deleted</string>
+
<!-- Preference for input language selection -->
<string name="select_language">Input languages</string>
@@ -289,7 +296,7 @@
<string name="subtype_locale">Language</string>
<!-- Title of the spinner for choosing a keyboard layout of custom style in the settings dialog [CHAR LIMIT=15] -->
<string name="keyboard_layout_set">Layout</string>
- <!-- The message of the dialog to note that a custom input style needs to be enabled. [CHAR LIMIT=64] -->
+ <!-- The message of the dialog to note that a custom input style needs to be enabled. [CHAR LIMIT=130] -->
<string name="custom_input_style_note_message">"Your custom input style needs to be enabled before you start using it. Do you want to enable it now?"</string>
<!-- Title of the button to enable a custom input style entry in the settings dialog [CHAR LIMIT=15] -->
<string name="enable">Enable</string>
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index 622da2120..162119dab 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -22,23 +22,8 @@
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
<!-- Base key style for the key which may have settings or tab key as popup key. -->
- <switch>
- <case
- latin:clobberSettingsKey="true"
- >
- <key-style
- latin:styleName="f1MoreKeysStyle"
- latin:backgroundType="functional" />
- </case>
- <!-- clobberSettingsKey="false" -->
- <default>
- <key-style
- latin:styleName="f1MoreKeysStyle"
- latin:keyLabelFlags="hasPopupHint"
- latin:moreKeys="!text/settings_as_more_key"
- latin:backgroundType="functional" />
- </default>
- </switch>
+ <include
+ latin:keyboardLayout="@xml/key_styles_f1" />
<!-- Functional key styles -->
<switch>
<case
diff --git a/java/res/xml/key_styles_f1.xml b/java/res/xml/key_styles_f1.xml
new file mode 100644
index 000000000..8dfc3cb84
--- /dev/null
+++ b/java/res/xml/key_styles_f1.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <!-- Base key style for the key which may have settings or tab key as popup key. -->
+ <!-- Kept as a separate file for cleaner overriding by an overlay. -->
+ <switch>
+ <case
+ latin:clobberSettingsKey="true"
+ >
+ <key-style
+ latin:styleName="f1MoreKeysStyle"
+ latin:backgroundType="functional" />
+ </case>
+ <!-- clobberSettingsKey="false" -->
+ <default>
+ <key-style
+ latin:styleName="f1MoreKeysStyle"
+ latin:keyLabelFlags="hasPopupHint"
+ latin:moreKeys="!text/settings_as_more_key"
+ latin:backgroundType="functional" />
+ </default>
+ </switch>
+</merge>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 137981949..bf8805875 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -81,6 +81,12 @@
android:title="@string/misc_category"
android:key="misc_settings">
<CheckBoxPreference
+ android:key="next_word_prediction"
+ android:title="@string/bigram_prediction"
+ android:summary="@string/bigram_prediction_summary"
+ android:persistent="true"
+ android:defaultValue="true" />
+ <CheckBoxPreference
android:key="usability_study_mode"
android:title="@string/prefs_usability_study_mode"
android:persistent="true"
@@ -114,24 +120,6 @@
android:summary="@string/use_contacts_dict_summary"
android:persistent="true"
android:defaultValue="true" />
- <CheckBoxPreference
- android:key="next_word_suggestion"
- android:title="@string/bigram_suggestion"
- android:summary="@string/bigram_suggestion_summary"
- android:persistent="true"
- android:defaultValue="true" />
- <CheckBoxPreference
- android:key="next_word_prediction"
- android:title="@string/bigram_prediction"
- android:summary="@string/bigram_prediction_summary"
- android:persistent="true"
- android:defaultValue="true" />
- <CheckBoxPreference
- android:key="enable_span_insert"
- android:title="@string/enable_span_insert"
- android:summary="@string/enable_span_insert_summary"
- android:persistent="true"
- android:defaultValue="true" />
<PreferenceScreen
android:key="pref_vibration_duration_settings"
android:title="@string/prefs_keypress_vibration_duration_settings"/>
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 23acb8b74..5ffd94a43 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.accessibility;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseIntArray;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.keyboard.Key;
@@ -39,8 +40,8 @@ public class KeyCodeDescriptionMapper {
// Map of key labels to spoken description resource IDs
private final HashMap<CharSequence, Integer> mKeyLabelMap;
- // Map of key codes to spoken description resource IDs
- private final HashMap<Integer, Integer> mKeyCodeMap;
+ // Sparse array of spoken description resource IDs indexed by key codes
+ private final SparseIntArray mKeyCodeMap;
public static void init() {
sInstance.initInternal();
@@ -52,7 +53,7 @@ public class KeyCodeDescriptionMapper {
private KeyCodeDescriptionMapper() {
mKeyLabelMap = new HashMap<CharSequence, Integer>();
- mKeyCodeMap = new HashMap<Integer, Integer>();
+ mKeyCodeMap = new SparseIntArray();
}
private void initInternal() {
@@ -60,7 +61,7 @@ public class KeyCodeDescriptionMapper {
mKeyLabelMap.put(":-)", R.string.spoken_description_smiley);
// Symbols that most TTS engines can't speak
- mKeyCodeMap.put((int) ' ', R.string.spoken_description_space);
+ mKeyCodeMap.put(' ', R.string.spoken_description_space);
// Special non-character codes defined in Keyboard
mKeyCodeMap.put(Keyboard.CODE_DELETE, R.string.spoken_description_delete);
@@ -273,7 +274,8 @@ public class KeyCodeDescriptionMapper {
return context.getString(OBSCURED_KEY_RES_ID);
}
- if (mKeyCodeMap.containsKey(code)) {
+ final int resId = mKeyCodeMap.get(code);
+ if (resId != 0) {
return context.getString(mKeyCodeMap.get(code));
} else if (isDefinedNonCtrl) {
return Character.toString((char) code);
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 21f175d7d..1b4cea2e7 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -23,6 +23,8 @@ import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.TypedValue;
import android.util.Xml;
import android.view.InflateException;
@@ -44,7 +46,6 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
@@ -89,7 +90,8 @@ public class Keyboard {
private static final int MINIMUM_LETTER_CODE = CODE_TAB;
/** Special keys code. Must be negative.
- * These should be aligned with values/keycodes.xml
+ * These should be aligned with KeyboardCodesSet.ID_TO_NAME[],
+ * KeyboardCodesSet.DEFAULT[] and KeyboardCodesSet.RTL[]
*/
public static final int CODE_SHIFT = -1;
public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
@@ -101,8 +103,9 @@ public class Keyboard {
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;
// Code value representing the code is not specified.
- public static final int CODE_UNSPECIFIED = -11;
+ public static final int CODE_UNSPECIFIED = -12;
public final KeyboardId mId;
public final int mThemeId;
@@ -132,7 +135,7 @@ public class Keyboard {
public final Key[] mAltCodeKeysWhileTyping;
public final KeyboardIconsSet mIconsSet;
- private final HashMap<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
+ private final SparseArray<Key> mKeyCache = new SparseArray<Key>();
private final ProximityInfo mProximityInfo;
private final boolean mProximityCharsCorrectionEnabled;
@@ -182,23 +185,23 @@ public class Keyboard {
if (code == CODE_UNSPECIFIED) {
return null;
}
- final Integer keyCode = code;
- if (mKeyCache.containsKey(keyCode)) {
- return mKeyCache.get(keyCode);
+ final int index = mKeyCache.indexOfKey(code);
+ if (index >= 0) {
+ return mKeyCache.valueAt(index);
}
for (final Key key : mKeys) {
if (key.mCode == code) {
- mKeyCache.put(keyCode, key);
+ mKeyCache.put(code, key);
return key;
}
}
- mKeyCache.put(keyCode, null);
+ mKeyCache.put(code, null);
return null;
}
public boolean hasKey(Key aKey) {
- if (mKeyCache.containsKey(aKey)) {
+ if (mKeyCache.indexOfValue(aKey) >= 0) {
return true;
}
@@ -342,8 +345,8 @@ public class Keyboard {
private int mMaxHeightCount = 0;
private int mMaxWidthCount = 0;
- private final HashMap<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
- private final HashMap<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
+ private final SparseIntArray mHeightHistogram = new SparseIntArray();
+ private final SparseIntArray mWidthHistogram = new SparseIntArray();
private void clearHistogram() {
mMostCommonKeyHeight = 0;
@@ -355,22 +358,22 @@ public class Keyboard {
mWidthHistogram.clear();
}
- private static int updateHistogramCounter(HashMap<Integer, Integer> histogram,
- Integer key) {
- final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
+ private static int updateHistogramCounter(SparseIntArray histogram, int key) {
+ final int index = histogram.indexOfKey(key);
+ final int count = (index >= 0 ? histogram.get(key) : 0) + 1;
histogram.put(key, count);
return count;
}
private void updateHistogram(Key key) {
- final Integer height = key.mHeight + key.mVerticalGap;
+ final int height = key.mHeight + key.mVerticalGap;
final int heightCount = updateHistogramCounter(mHeightHistogram, height);
if (heightCount > mMaxHeightCount) {
mMaxHeightCount = heightCount;
mMostCommonKeyHeight = height;
}
- final Integer width = key.mWidth + key.mHorizontalGap;
+ final int width = key.mWidth + key.mHorizontalGap;
final int widthCount = updateHistogramCounter(mWidthHistogram, width);
if (widthCount > mMaxWidthCount) {
mMaxWidthCount = widthCount;
@@ -422,67 +425,67 @@ public class Keyboard {
* This class parses Keyboard XML file and eventually build a Keyboard.
* The Keyboard XML file looks like:
* <pre>
- * &gt;!-- xml/keyboard.xml --&lt;
- * &gt;Keyboard keyboard_attributes*&lt;
- * &gt;!-- Keyboard Content --&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;!-- Row Content --&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;Spacer horizontalGap="32.0dp" /&lt;
- * &gt;include keyboardLayout="@xml/other_keys"&lt;
+ * &lt;!-- xml/keyboard.xml --&gt;
+ * &lt;Keyboard keyboard_attributes*&gt;
+ * &lt;!-- Keyboard Content --&gt;
+ * &lt;Row row_attributes*&gt;
+ * &lt;!-- Row Content --&gt;
+ * &lt;Key key_attributes* /&gt;
+ * &lt;Spacer horizontalGap="32.0dp" /&gt;
+ * &lt;include keyboardLayout="@xml/other_keys"&gt;
* ...
- * &gt;/Row&lt;
- * &gt;include keyboardLayout="@xml/other_rows"&lt;
+ * &lt;/Row&gt;
+ * &lt;include keyboardLayout="@xml/other_rows"&gt;
* ...
- * &gt;/Keyboard&lt;
+ * &lt;/Keyboard&gt;
* </pre>
- * The XML file which is included in other file must have &gt;merge&lt; as root element,
+ * The XML file which is included in other file must have &lt;merge&gt; as root element,
* such as:
* <pre>
- * &gt;!-- xml/other_keys.xml --&lt;
- * &gt;merge&lt;
- * &gt;Key key_attributes* /&lt;
+ * &lt;!-- xml/other_keys.xml --&gt;
+ * &lt;merge&gt;
+ * &lt;Key key_attributes* /&gt;
* ...
- * &gt;/merge&lt;
+ * &lt;/merge&gt;
* </pre>
* and
* <pre>
- * &gt;!-- xml/other_rows.xml --&lt;
- * &gt;merge&lt;
- * &gt;Row row_attributes*&lt;
- * &gt;Key key_attributes* /&lt;
- * &gt;/Row&lt;
+ * &lt;!-- xml/other_rows.xml --&gt;
+ * &lt;merge&gt;
+ * &lt;Row row_attributes*&gt;
+ * &lt;Key key_attributes* /&gt;
+ * &lt;/Row&gt;
* ...
- * &gt;/merge&lt;
+ * &lt;/merge&gt;
* </pre>
* You can also use switch-case-default tags to select Rows and Keys.
* <pre>
- * &gt;switch&lt;
- * &gt;case case_attribute*&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/case&lt;
+ * &lt;switch&gt;
+ * &lt;case case_attribute*&gt;
+ * &lt;!-- Any valid tags at switch position --&gt;
+ * &lt;/case&gt;
* ...
- * &gt;default&lt;
- * &gt;!-- Any valid tags at switch position --&lt;
- * &gt;/default&lt;
- * &gt;/switch&lt;
+ * &lt;default&gt;
+ * &lt;!-- Any valid tags at switch position --&gt;
+ * &lt;/default&gt;
+ * &lt;/switch&gt;
* </pre>
* You can declare Key style and specify styles within Key tags.
* <pre>
- * &gt;switch&lt;
- * &gt;case mode="email"&lt;
- * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
+ * &lt;switch&gt;
+ * &lt;case mode="email"&gt;
+ * &lt;key-style styleName="f1-key" parentStyle="modifier-key"
* keyLabel=".com"
- * /&lt;
- * &gt;/case&lt;
- * &gt;case mode="url"&lt;
- * &gt;key-style styleName="f1-key" parentStyle="modifier-key"
+ * /&gt;
+ * &lt;/case&gt;
+ * &lt;case mode="url"&gt;
+ * &lt;key-style styleName="f1-key" parentStyle="modifier-key"
* keyLabel="http://"
- * /&lt;
- * &gt;/case&lt;
- * &gt;/switch&lt;
+ * /&gt;
+ * &lt;/case&gt;
+ * &lt;/switch&gt;
* ...
- * &gt;Key keyStyle="shift-key" ... /&lt;
+ * &lt;Key keyStyle="shift-key" ... /&gt;
* </pre>
*/
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index 8c7246855..aab89a3e5 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -29,6 +29,7 @@ import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.text.InputType;
import android.util.Log;
+import android.util.SparseArray;
import android.util.Xml;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
@@ -116,9 +117,9 @@ public class KeyboardLayoutSet {
InputMethodSubtype mSubtype;
int mOrientation;
int mWidth;
- // KeyboardLayoutSet element id to element's parameters map.
- final HashMap<Integer, ElementParams> mKeyboardLayoutSetElementIdToParamsMap =
- new HashMap<Integer, ElementParams>();
+ // Sparse array of KeyboardLayoutSet element parameters indexed by element's id.
+ final SparseArray<ElementParams> mKeyboardLayoutSetElementIdToParamsMap =
+ new SparseArray<ElementParams>();
static class ElementParams {
int mKeyboardXmlId;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 51a0f537f..fb98af3e6 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -30,6 +30,7 @@ import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Message;
import android.util.AttributeSet;
+import android.util.SparseArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,7 +43,6 @@ import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import com.android.inputmethod.latin.StringUtils;
-import java.util.HashMap;
import java.util.HashSet;
/**
@@ -124,12 +124,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
private Canvas mCanvas;
private final Paint mPaint = new Paint();
private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
- // This map caches key label text height in pixel as value and key label text size as map key.
- private static final HashMap<Integer, Float> sTextHeightCache =
- new HashMap<Integer, Float>();
- // This map caches key label text width in pixel as value and key label text size as map key.
- private static final HashMap<Integer, Float> sTextWidthCache =
- new HashMap<Integer, Float>();
+ // This sparse array caches key label text height in pixel indexed by key label text size.
+ private static final SparseArray<Float> sTextHeightCache = new SparseArray<Float>();
+ // This sparse array caches key label text width in pixel indexed by key label text size.
+ private static final SparseArray<Float> sTextWidthCache = new SparseArray<Float>();
private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' };
private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' };
@@ -766,7 +764,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
private final Rect mTextBounds = new Rect();
private float getCharHeight(char[] referenceChar, Paint paint) {
- final Integer key = getCharGeometryCacheKey(referenceChar[0], paint);
+ final int key = getCharGeometryCacheKey(referenceChar[0], paint);
final Float cachedValue = sTextHeightCache.get(key);
if (cachedValue != null)
return cachedValue;
@@ -778,7 +776,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
private float getCharWidth(char[] referenceChar, Paint paint) {
- final Integer key = getCharGeometryCacheKey(referenceChar[0], paint);
+ final int key = getCharGeometryCacheKey(referenceChar[0], paint);
final Float cachedValue = sTextWidthCache.get(key);
if (cachedValue != null)
return cachedValue;
@@ -873,6 +871,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacer, 0, 0));
}
+ @SuppressWarnings("deprecation") // setBackgroundDrawable is replaced by setBackground in API16
@Override
public void showKeyPreview(PointerTracker tracker) {
if (!mShowKeyPreviewPopup) return;
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 383298de9..7714ba892 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -127,7 +127,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
private static final int MSG_TYPING_STATE_EXPIRED = 4;
private final KeyTimerParams mParams;
- private boolean mInKeyRepeat;
public KeyTimerHandler(LatinKeyboardView outerInstance, KeyTimerParams params) {
super(outerInstance);
@@ -140,8 +139,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
final PointerTracker tracker = (PointerTracker) msg.obj;
switch (msg.what) {
case MSG_REPEAT_KEY:
- tracker.onRegisterKey(tracker.getKey());
- startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
+ final Key currentKey = tracker.getKey();
+ if (currentKey != null && currentKey.mCode == msg.arg1) {
+ tracker.onRegisterKey(currentKey);
+ startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval);
+ }
break;
case MSG_LONGPRESS_KEY:
if (tracker != null) {
@@ -158,22 +160,23 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
}
private void startKeyRepeatTimer(PointerTracker tracker, long delay) {
- sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker), delay);
+ final Key key = tracker.getKey();
+ if (key == null) return;
+ sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, key.mCode, 0, tracker), delay);
}
@Override
public void startKeyRepeatTimer(PointerTracker tracker) {
- mInKeyRepeat = true;
startKeyRepeatTimer(tracker, mParams.mKeyRepeatStartTimeout);
}
public void cancelKeyRepeatTimer() {
- mInKeyRepeat = false;
removeMessages(MSG_REPEAT_KEY);
}
+ // TODO: Suppress layout changes in key repeat mode
public boolean isInKeyRepeat() {
- return mInKeyRepeat;
+ return hasMessages(MSG_REPEAT_KEY);
}
@Override
@@ -451,8 +454,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
*/
@Override
public void setKeyboard(Keyboard keyboard) {
- // Remove any pending messages, except dismissing preview
- mKeyTimerHandler.cancelKeyTimers();
+ // Remove any pending messages, except dismissing preview and key repeat.
+ mKeyTimerHandler.cancelLongPressTimer();
super.setKeyboard(keyboard);
mKeyDetector.setKeyboard(
keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
@@ -755,15 +758,18 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
final PointerTracker tracker = PointerTracker.getPointerTracker(
pointerId, this);
final int px, py;
+ final MotionEvent motionEvent;
if (mMoreKeysPanel != null
&& tracker.mPointerId == mMoreKeysPanelPointerTrackerId) {
px = mMoreKeysPanel.translateX((int)me.getX(i));
py = mMoreKeysPanel.translateY((int)me.getY(i));
+ motionEvent = null;
} else {
px = (int)me.getX(i);
py = (int)me.getY(i);
+ motionEvent = me;
}
- tracker.onMoveEvent(px, py, eventTime);
+ tracker.onMoveEvent(px, py, eventTime, motionEvent);
if (ENABLE_USABILITY_STUDY_LOG) {
final float pointerSize = me.getSize(i);
final float pointerPressure = me.getPressure(i);
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index babf6ec99..32ef408b4 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -148,9 +148,6 @@ public class PointerTracker {
// true if this pointer has been long-pressed and is showing a more keys panel.
private boolean mIsShowingMoreKeysPanel;
- // true if this pointer is repeatable key
- private boolean mIsRepeatableKey;
-
// true if this pointer is in sliding key input
boolean mIsInSlidingKeyInput;
@@ -242,10 +239,6 @@ public class PointerTracker {
+ " ignoreModifier=" + ignoreModifierKey
+ " enabled=" + key.isEnabled());
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key,
- ignoreModifierKey);
- }
if (ignoreModifierKey) {
return false;
}
@@ -323,6 +316,13 @@ public class PointerTracker {
private void setKeyDetectorInner(KeyDetector keyDetector) {
mKeyDetector = keyDetector;
mKeyboard = keyDetector.getKeyboard();
+ final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
+ if (newKey != mCurrentKey) {
+ if (mDrawingProxy != null) {
+ setReleasedKeyGraphics(mCurrentKey);
+ }
+ mCurrentKey = newKey;
+ }
final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4;
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
}
@@ -469,7 +469,7 @@ public class PointerTracker {
onUpEvent(x, y, eventTime);
break;
case MotionEvent.ACTION_MOVE:
- onMoveEvent(x, y, eventTime);
+ onMoveEvent(x, y, eventTime, null);
break;
case MotionEvent.ACTION_CANCEL:
onCancelEvent(x, y, eventTime);
@@ -525,7 +525,6 @@ public class PointerTracker {
|| mKeyDetector.alwaysAllowsSlidingInput();
mKeyboardLayoutHasBeenChanged = false;
mKeyAlreadyProcessed = false;
- mIsRepeatableKey = false;
mIsInSlidingKeyInput = false;
mIgnoreModifierKey = false;
if (key != null) {
@@ -549,7 +548,7 @@ public class PointerTracker {
mIsInSlidingKeyInput = true;
}
- public void onMoveEvent(int x, int y, long eventTime) {
+ public void onMoveEvent(int x, int y, long eventTime, MotionEvent me) {
if (DEBUG_MOVE_EVENT)
printTouchEvent("onMoveEvent:", x, y, eventTime);
if (mKeyAlreadyProcessed)
@@ -672,7 +671,7 @@ public class PointerTracker {
}
if (mKeyAlreadyProcessed)
return;
- if (!mIsRepeatableKey) {
+ if (mCurrentKey != null && !mCurrentKey.isRepeatable()) {
detectAndSendKey(mCurrentKey, mKeyX, mKeyY);
}
}
@@ -718,9 +717,6 @@ public class PointerTracker {
if (key != null && key.isRepeatable()) {
onRegisterKey(key);
mTimerProxy.startKeyRepeatTimer(this);
- mIsRepeatableKey = true;
- } else {
- mIsRepeatableKey = false;
}
}
@@ -764,14 +760,10 @@ public class PointerTracker {
callListenerOnRelease(key, code, false);
}
- private long mPreviousEventTime;
-
private void printTouchEvent(String title, int x, int y, long eventTime) {
final Key key = mKeyDetector.detectHitKey(x, y);
final String code = KeyDetector.printableCode(key);
- final long delta = eventTime - mPreviousEventTime;
Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %s", title,
- (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, code));
- mPreviousEventTime = eventTime;
+ (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, eventTime, code));
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 1207c3fcd..ae123e29a 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -24,9 +24,10 @@ import com.android.inputmethod.keyboard.Keyboard.Params.TouchPositionCorrection;
import com.android.inputmethod.latin.JniUtils;
import java.util.Arrays;
-import java.util.HashMap;
public class ProximityInfo {
+ /** MAX_PROXIMITY_CHARS_SIZE must be the same as MAX_PROXIMITY_CHARS_SIZE_INTERNAL
+ * in defines.h */
public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
/** Number of key widths from current touch point to search for nearest keys. */
private static float SEARCH_DISTANCE = 1.2f;
@@ -75,27 +76,6 @@ public class ProximityInfo {
mNativeProximityInfo = createNativeProximityInfo();
}
- // TODO: Remove this public constructor when the native part of the ProximityInfo becomes
- // immutable.
- // This public constructor aims only for test purpose.
- public ProximityInfo(ProximityInfo o) {
- mLocaleStr = o.mLocaleStr;
- mGridWidth = o.mGridWidth;
- mGridHeight = o.mGridHeight;
- mGridSize = o.mGridSize;
- mCellWidth = o.mCellWidth;
- mCellHeight = o.mCellHeight;
- mKeyboardMinWidth = o.mKeyboardMinWidth;
- mKeyboardHeight = o.mKeyboardHeight;
- mKeyHeight = o.mKeyHeight;
- mMostCommonKeyWidth = o.mMostCommonKeyWidth;
- mKeys = o.mKeys;
- mTouchPositionCorrection = o.mTouchPositionCorrection;
- mGridNeighbors = new Key[mGridSize][];
- computeNearestNeighbors();
- mNativeProximityInfo = createNativeProximityInfo();
- }
-
public static ProximityInfo createDummyProximityInfo() {
return new ProximityInfo("", 1, 1, 1, 1, 1, 1, EMPTY_KEY_ARRAY, null);
}
@@ -209,10 +189,6 @@ public class ProximityInfo {
private void computeNearestNeighbors() {
final int defaultWidth = mMostCommonKeyWidth;
final Key[] keys = mKeys;
- final HashMap<Integer, Key> keyCodeMap = new HashMap<Integer, Key>();
- for (final Key key : keys) {
- keyCodeMap.put(key.mCode, key);
- }
final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
final int threshold = thresholdBase * thresholdBase;
// Round-up so we don't have any pixels outside the grid
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 80f4f259b..291b3b943 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard.internal;
import android.content.res.TypedArray;
import android.util.Log;
+import android.util.SparseArray;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.R;
@@ -89,7 +90,7 @@ public class KeyStyles {
private class DeclaredKeyStyle extends KeyStyle {
private final String mParentStyleName;
- private final HashMap<Integer, Object> mStyleAttributes = new HashMap<Integer, Object>();
+ private final SparseArray<Object> mStyleAttributes = new SparseArray<Object>();
public DeclaredKeyStyle(String parentStyleName) {
mParentStyleName = parentStyleName;
@@ -100,8 +101,9 @@ public class KeyStyles {
if (a.hasValue(index)) {
return parseStringArray(a, index);
}
- if (mStyleAttributes.containsKey(index)) {
- return (String[])mStyleAttributes.get(index);
+ final Object value = mStyleAttributes.get(index);
+ if (value != null) {
+ return (String[])value;
}
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
return parentStyle.getStringArray(a, index);
@@ -112,8 +114,9 @@ public class KeyStyles {
if (a.hasValue(index)) {
return parseString(a, index);
}
- if (mStyleAttributes.containsKey(index)) {
- return (String)mStyleAttributes.get(index);
+ final Object value = mStyleAttributes.get(index);
+ if (value != null) {
+ return (String)value;
}
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
return parentStyle.getString(a, index);
@@ -124,8 +127,9 @@ public class KeyStyles {
if (a.hasValue(index)) {
return a.getInt(index, defaultValue);
}
- if (mStyleAttributes.containsKey(index)) {
- return (Integer)mStyleAttributes.get(index);
+ final Object value = mStyleAttributes.get(index);
+ if (value != null) {
+ return (Integer)value;
}
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
return parentStyle.getInt(a, index, defaultValue);
@@ -133,12 +137,13 @@ public class KeyStyles {
@Override
public int getFlag(TypedArray a, int index) {
- int value = a.getInt(index, 0);
- if (mStyleAttributes.containsKey(index)) {
- value |= (Integer)mStyleAttributes.get(index);
+ int flags = a.getInt(index, 0);
+ final Object value = mStyleAttributes.get(index);
+ if (value != null) {
+ flags |= (Integer)value;
}
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
- return value | parentStyle.getFlag(a, index);
+ return flags | parentStyle.getFlag(a, index);
}
void readKeyAttributes(TypedArray keyAttr) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
index 67cb74f4d..f7981a320 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -52,6 +52,7 @@ public class KeyboardCodesSet {
"key_action_next",
"key_action_previous",
"key_language_switch",
+ "key_research",
"key_unspecified",
"key_left_parenthesis",
"key_right_parenthesis",
@@ -86,6 +87,7 @@ public class KeyboardCodesSet {
Keyboard.CODE_ACTION_NEXT,
Keyboard.CODE_ACTION_PREVIOUS,
Keyboard.CODE_LANGUAGE_SWITCH,
+ Keyboard.CODE_RESEARCH,
Keyboard.CODE_UNSPECIFIED,
CODE_LEFT_PARENTHESIS,
CODE_RIGHT_PARENTHESIS,
@@ -112,6 +114,7 @@ public class KeyboardCodesSet {
DEFAULT[11],
DEFAULT[12],
DEFAULT[13],
+ DEFAULT[14],
CODE_RIGHT_PARENTHESIS,
CODE_LEFT_PARENTHESIS,
CODE_GREATER_THAN_SIGN,
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 540e63b3f..5155851fe 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -20,6 +20,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.Log;
+import android.util.SparseIntArray;
import com.android.inputmethod.latin.R;
@@ -31,8 +32,7 @@ public class KeyboardIconsSet {
public static final int ICON_UNDEFINED = 0;
private static final int ATTR_UNDEFINED = 0;
- private static final HashMap<Integer, Integer> ATTR_ID_TO_ICON_ID
- = new HashMap<Integer, Integer>();
+ private static final SparseIntArray ATTR_ID_TO_ICON_ID = new SparseIntArray();
// Icon name to icon id map.
private static final HashMap<String, Integer> sNameToIdsMap = new HashMap<String, Integer>();
@@ -76,7 +76,9 @@ public class KeyboardIconsSet {
}
public void loadIcons(final TypedArray keyboardAttrs) {
- for (final Integer attrId : ATTR_ID_TO_ICON_ID.keySet()) {
+ final int size = ATTR_ID_TO_ICON_ID.size();
+ for (int index = 0; index < size; index++) {
+ final int attrId = ATTR_ID_TO_ICON_ID.keyAt(index);
try {
final Drawable icon = keyboardAttrs.getDrawable(attrId);
setDefaultBounds(icon);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 43ffb85f7..4ab6832c3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -21,8 +21,6 @@ import android.util.Log;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.ResearchLogger;
-import com.android.inputmethod.latin.define.ProductionFlag;
/**
* Keyboard state machine.
@@ -305,9 +303,6 @@ public class KeyboardState {
Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code)
+ " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onPressKey(code, this);
- }
if (code == Keyboard.CODE_SHIFT) {
onPressShift();
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
@@ -341,9 +336,6 @@ public class KeyboardState {
Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code)
+ " sliding=" + withSliding + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding);
- }
if (code == Keyboard.CODE_SHIFT) {
onReleaseShift(withSliding);
} else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) {
@@ -375,9 +367,6 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onLongPressTimeout(code, this);
- }
if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) {
mLongPressShiftLockFired = true;
mSwitchActions.hapticAndAudioFeedback(code);
@@ -509,9 +498,6 @@ public class KeyboardState {
if (DEBUG_EVENT) {
Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this);
- }
// Switch back to the previous keyboard mode if the user cancels sliding input.
if (isSinglePointer) {
if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) {
@@ -543,9 +529,6 @@ public class KeyboardState {
+ " single=" + isSinglePointer
+ " autoCaps=" + autoCaps + " " + this);
}
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this);
- }
switch (mSwitchState) {
case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java
index e0452483c..3eb53fca6 100644
--- a/java/src/com/android/inputmethod/latin/AutoCorrection.java
+++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java
@@ -21,7 +21,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import android.text.TextUtils;
import android.util.Log;
-import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
public class AutoCorrection {
@@ -32,23 +31,6 @@ public class AutoCorrection {
// Purely static class: can't instantiate.
}
- public static CharSequence computeAutoCorrectionWord(
- final ConcurrentHashMap<String, Dictionary> dictionaries,
- final WordComposer wordComposer, final ArrayList<SuggestedWordInfo> suggestions,
- final CharSequence consideredWord, final float autoCorrectionThreshold,
- final CharSequence whitelistedWord) {
- if (hasAutoCorrectionForWhitelistedWord(whitelistedWord)) {
- return whitelistedWord;
- } else if (hasAutoCorrectionForConsideredWord(
- dictionaries, wordComposer, suggestions, consideredWord)) {
- return consideredWord;
- } else if (hasAutoCorrectionForBinaryDictionary(wordComposer, suggestions,
- consideredWord, autoCorrectionThreshold)) {
- return suggestions.get(0).mWord;
- }
- return null;
- }
-
public static boolean isValidWord(final ConcurrentHashMap<String, Dictionary> dictionaries,
CharSequence word, boolean ignoreCase) {
if (TextUtils.isEmpty(word)) {
@@ -56,7 +38,7 @@ public class AutoCorrection {
}
final CharSequence lowerCasedWord = word.toString().toLowerCase();
for (final String key : dictionaries.keySet()) {
- if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue;
+ if (key.equals(Dictionary.TYPE_WHITELIST)) continue;
final Dictionary dictionary = dictionaries.get(key);
// It's unclear how realistically 'dictionary' can be null, but the monkey is somehow
// managing to get null in here. Presumably the language is changing to a language with
@@ -81,7 +63,7 @@ public class AutoCorrection {
}
int maxFreq = -1;
for (final String key : dictionaries.keySet()) {
- if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue;
+ if (key.equals(Dictionary.TYPE_WHITELIST)) continue;
final Dictionary dictionary = dictionaries.get(key);
if (null == dictionary) continue;
final int tempFreq = dictionary.getFrequency(word);
@@ -92,11 +74,12 @@ public class AutoCorrection {
return maxFreq;
}
- public static boolean allowsToBeAutoCorrected(
+ // Returns true if this is a whitelist entry, or it isn't in any dictionary.
+ public static boolean isWhitelistedOrNotAWord(
final ConcurrentHashMap<String, Dictionary> dictionaries,
final CharSequence word, final boolean ignoreCase) {
final WhitelistDictionary whitelistDictionary =
- (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST);
+ (WhitelistDictionary)dictionaries.get(Dictionary.TYPE_WHITELIST);
// If "word" is in the whitelist dictionary, it should not be auto corrected.
if (whitelistDictionary != null
&& whitelistDictionary.shouldForciblyAutoCorrectFrom(word)) {
@@ -105,33 +88,18 @@ public class AutoCorrection {
return !isValidWord(dictionaries, word, ignoreCase);
}
- private static boolean hasAutoCorrectionForWhitelistedWord(CharSequence whiteListedWord) {
- return whiteListedWord != null;
- }
-
- private static boolean hasAutoCorrectionForConsideredWord(
- final ConcurrentHashMap<String, Dictionary> dictionaries,
- final WordComposer wordComposer, final ArrayList<SuggestedWordInfo> suggestions,
- final CharSequence consideredWord) {
- if (TextUtils.isEmpty(consideredWord)) return false;
- return wordComposer.size() > 1 && suggestions.size() > 0
- && !allowsToBeAutoCorrected(dictionaries, consideredWord, false);
- }
-
- private static boolean hasAutoCorrectionForBinaryDictionary(WordComposer wordComposer,
- ArrayList<SuggestedWordInfo> suggestions,
+ public static boolean suggestionExceedsAutoCorrectionThreshold(SuggestedWordInfo suggestion,
CharSequence consideredWord, float autoCorrectionThreshold) {
- if (wordComposer.size() > 1 && suggestions.size() > 0) {
- final SuggestedWordInfo autoCorrectionSuggestion = suggestions.get(0);
+ if (null != suggestion) {
//final int autoCorrectionSuggestionScore = sortedScores[0];
- final int autoCorrectionSuggestionScore = autoCorrectionSuggestion.mScore;
+ final int autoCorrectionSuggestionScore = suggestion.mScore;
// TODO: when the normalized score of the first suggestion is nearly equals to
// the normalized score of the second suggestion, behave less aggressive.
final float normalizedScore = BinaryDictionary.calcNormalizedScore(
- consideredWord.toString(), autoCorrectionSuggestion.mWord.toString(),
+ consideredWord.toString(), suggestion.mWord.toString(),
autoCorrectionSuggestionScore);
if (DBG) {
- Log.d(TAG, "Normalized " + consideredWord + "," + autoCorrectionSuggestion + ","
+ Log.d(TAG, "Normalized " + consideredWord + "," + suggestion + ","
+ autoCorrectionSuggestionScore + ", " + normalizedScore
+ "(" + autoCorrectionThreshold + ")");
}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index d0613bd72..ae415d0ab 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -20,7 +20,9 @@ import android.content.Context;
import android.text.TextUtils;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
@@ -40,17 +42,18 @@ public class BinaryDictionary extends Dictionary {
*/
public static final int MAX_WORD_LENGTH = 48;
public static final int MAX_WORDS = 18;
+ public static final int MAX_SPACES = 16;
private static final String TAG = "BinaryDictionary";
private static final int MAX_BIGRAMS = 60;
private static final int TYPED_LETTER_MULTIPLIER = 2;
- private int mDicTypeId;
private long mNativeDict;
private final int[] mInputCodes = new int[MAX_WORD_LENGTH];
private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS];
private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS];
+ private final int[] mSpaceIndices = new int[MAX_SPACES];
private final int[] mScores = new int[MAX_WORDS];
private final int[] mBigramScores = new int[MAX_BIGRAMS];
@@ -65,14 +68,12 @@ public class BinaryDictionary extends Dictionary {
* @param offset the offset of the dictionary data within the file.
* @param length the length of the binary data.
* @param useFullEditDistance whether to use the full edit distance in suggestions
+ * @param dictType the dictionary type, as a human-readable string
*/
public BinaryDictionary(final Context context,
final String filename, final long offset, final long length,
- final boolean useFullEditDistance, final Locale locale) {
- // Note: at the moment a binary dictionary is always of the "main" type.
- // Initializing this here will help transitioning out of the scheme where
- // the Suggest class knows everything about every single dictionary.
- mDicTypeId = Suggest.DIC_MAIN;
+ final boolean useFullEditDistance, final Locale locale, final String dictType) {
+ super(dictType);
mUseFullEditDistance = useFullEditDistance;
loadDictionary(filename, offset, length);
}
@@ -87,8 +88,10 @@ public class BinaryDictionary extends Dictionary {
private native int getFrequencyNative(long dict, int[] word, int wordLength);
private native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates,
- int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams,
- boolean useFullEditDistance, char[] outputChars, int[] scores);
+ int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodes, int codesSize,
+ int commitPoint, boolean isGesture,
+ int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars,
+ int[] scores, int[] outputIndices);
private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength,
int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores,
int maxWordLength, int maxBigrams);
@@ -103,9 +106,9 @@ public class BinaryDictionary extends Dictionary {
}
@Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
- if (mNativeDict == 0) return;
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+ final CharSequence previousWord) {
+ if (mNativeDict == 0) return null;
int[] codePoints = StringUtils.toCodePointArray(previousWord.toString());
Arrays.fill(mOutputChars_bigrams, (char) 0);
@@ -123,6 +126,7 @@ public class BinaryDictionary extends Dictionary {
count = MAX_BIGRAMS;
}
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
for (int j = 0; j < count; ++j) {
if (codesSize > 0 && mBigramScores[j] < 1) break;
final int start = j * MAX_WORD_LENGTH;
@@ -131,19 +135,22 @@ public class BinaryDictionary extends Dictionary {
++len;
}
if (len > 0) {
- callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j],
- mDicTypeId, Dictionary.BIGRAM);
+ suggestions.add(new SuggestedWordInfo(
+ new String(mOutputChars_bigrams, start, len),
+ mBigramScores[j], SuggestedWordInfo.KIND_CORRECTION, mDictType));
}
}
+ return suggestions;
}
// proximityInfo and/or prevWordForBigrams may not be null.
@Override
- public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
final int count = getSuggestions(codes, prevWordForBigrams, proximityInfo, mOutputChars,
- mScores);
+ mScores, mSpaceIndices);
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
for (int j = 0; j < count; ++j) {
if (mScores[j] < 1) break;
final int start = j * MAX_WORD_LENGTH;
@@ -152,10 +159,13 @@ public class BinaryDictionary extends Dictionary {
++len;
}
if (len > 0) {
- callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId,
- Dictionary.UNIGRAM);
+ // TODO: actually get the kind from native code
+ suggestions.add(new SuggestedWordInfo(
+ new String(mOutputChars, start, len),
+ mScores[j], SuggestedWordInfo.KIND_CORRECTION, mDictType));
}
}
+ return suggestions;
}
/* package for test */ boolean isValidDictionary() {
@@ -165,7 +175,7 @@ public class BinaryDictionary extends Dictionary {
// proximityInfo may not be null.
/* package for test */ int getSuggestions(final WordComposer codes,
final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo,
- char[] outputChars, int[] scores) {
+ char[] outputChars, int[] scores, int[] spaceIndices) {
if (!isValidDictionary()) return -1;
final int codesSize = codes.size();
@@ -179,14 +189,22 @@ public class BinaryDictionary extends Dictionary {
Arrays.fill(outputChars, (char) 0);
Arrays.fill(scores, 0);
- final int[] prevWordCodePointArray = null == prevWordForBigrams
+ // TODO: toLowerCase in the native code
+ final int[] prevWordCodePointArray = (null == prevWordForBigrams)
? null : StringUtils.toCodePointArray(prevWordForBigrams.toString());
- // TODO: pass the previous word to native code
- return getSuggestionsNative(
- mNativeDict, proximityInfo.getNativeProximityInfo(),
- codes.getXCoordinates(), codes.getYCoordinates(), mInputCodes, codesSize,
- prevWordCodePointArray, mUseFullEditDistance, outputChars, scores);
+ int[] emptyArray = new int[codesSize];
+ Arrays.fill(emptyArray, 0);
+
+ //final int commitPoint = codes.getCommitPoint();
+ //codes.clearCommitPoint();
+
+ final InputPointers ips = codes.getInputPointers();
+
+ return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
+ ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(),
+ mInputCodes, codesSize, 0 /* unused */, false, prevWordCodePointArray,
+ mUseFullEditDistance, outputChars, scores, spaceIndices);
}
public static float calcNormalizedScore(String before, String after, int score) {
diff --git a/java/src/com/android/inputmethod/latin/BoundedTreeSet.java b/java/src/com/android/inputmethod/latin/BoundedTreeSet.java
new file mode 100644
index 000000000..cf977617d
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/BoundedTreeSet.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.TreeSet;
+
+/**
+ * A TreeSet that is bounded in size and throws everything that's smaller than its limit
+ */
+public class BoundedTreeSet extends TreeSet<SuggestedWordInfo> {
+ private final int mCapacity;
+ public BoundedTreeSet(final Comparator<SuggestedWordInfo> comparator, final int capacity) {
+ super(comparator);
+ mCapacity = capacity;
+ }
+
+ @Override
+ public boolean add(final SuggestedWordInfo e) {
+ if (size() < mCapacity) return super.add(e);
+ if (comparator().compare(e, last()) > 0) return false;
+ super.add(e);
+ pollLast(); // removes the last element
+ return true;
+ }
+
+ @Override
+ public boolean addAll(final Collection<? extends SuggestedWordInfo> e) {
+ if (null == e) return false;
+ return super.addAll(e);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 34308dfb3..5edc4314f 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -52,6 +52,9 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
/** The number of contacts in the most recent dictionary rebuild. */
static private int sContactCountAtLastRebuild = 0;
+ /** The locale for this contacts dictionary. Controls name bigram predictions. */
+ public final Locale mLocale;
+
private ContentObserver mObserver;
/**
@@ -59,8 +62,9 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
*/
private final boolean mUseFirstLastBigrams;
- public ContactsBinaryDictionary(final Context context, final int dicTypeId, Locale locale) {
- super(context, getFilenameWithLocale(NAME, locale.toString()), dicTypeId);
+ public ContactsBinaryDictionary(final Context context, Locale locale) {
+ super(context, getFilenameWithLocale(NAME, locale.toString()), Dictionary.TYPE_CONTACTS);
+ mLocale = locale;
mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
registerObserver(context);
@@ -116,12 +120,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
}
}
- @Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
- super.getBigrams(codes, previousWord, callback);
- }
-
private boolean useFirstLastBigramsForLocale(Locale locale) {
// TODO: Add firstname/lastname bigram rules for other languages.
if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
@@ -163,7 +161,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
* bigrams depending on locale.
*/
private void addName(String name) {
- int len = name.codePointCount(0, name.length());
+ int len = StringUtils.codePointCount(name);
String prevWord = null;
// TODO: Better tokenization for non-Latin writing systems
for (int i = 0; i < len; i++) {
@@ -173,7 +171,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
i = end - 1;
// Don't add single letter words, possibly confuses
// capitalization of i.
- final int wordLen = word.codePointCount(0, word.length());
+ final int wordLen = StringUtils.codePointCount(word);
if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS);
if (!TextUtils.isEmpty(prevWord)) {
@@ -262,14 +260,14 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
* Checks if the words in a name are in the current binary dictionary.
*/
private boolean isNameInDictionary(String name) {
- int len = name.codePointCount(0, name.length());
+ int len = StringUtils.codePointCount(name);
String prevWord = null;
for (int i = 0; i < len; i++) {
if (Character.isLetter(name.codePointAt(i))) {
int end = getWordEndPosition(name, len, i);
String word = name.substring(i, end);
i = end - 1;
- final int wordLen = word.codePointCount(0, word.length());
+ final int wordLen = StringUtils.codePointCount(word);
if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) {
if (!super.isValidBigramLocked(prevWord, word)) {
diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
deleted file mode 100644
index cbfbd0ec8..000000000
--- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.os.SystemClock;
-import android.provider.BaseColumns;
-import android.provider.ContactsContract.Contacts;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.inputmethod.keyboard.Keyboard;
-
-// TODO: This class is superseded by {@link ContactsBinaryDictionary}. Should be cleaned up.
-/**
- * An expandable dictionary that stores the words from Contacts provider.
- *
- * @deprecated Use {@link ContactsBinaryDictionary}.
- */
-@Deprecated
-public class ContactsDictionary extends ExpandableDictionary {
-
- private static final String[] PROJECTION = {
- BaseColumns._ID,
- Contacts.DISPLAY_NAME,
- };
-
- private static final String TAG = "ContactsDictionary";
-
- /**
- * Frequency for contacts information into the dictionary
- */
- private static final int FREQUENCY_FOR_CONTACTS = 40;
- private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;
-
- private static final int INDEX_NAME = 1;
-
- private ContentObserver mObserver;
-
- private long mLastLoadedContacts;
-
- public ContactsDictionary(final Context context, final int dicTypeId) {
- super(context, dicTypeId);
- registerObserver(context);
- loadDictionary();
- }
-
- private synchronized void registerObserver(final Context context) {
- // Perform a managed query. The Activity will handle closing and requerying the cursor
- // when needed.
- if (mObserver != null) return;
- ContentResolver cres = context.getContentResolver();
- cres.registerContentObserver(
- Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean self) {
- setRequiresReload(true);
- }
- });
- }
-
- public void reopen(final Context context) {
- registerObserver(context);
- }
-
- @Override
- public synchronized void close() {
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- super.close();
- }
-
- @Override
- public void startDictionaryLoadingTaskLocked() {
- long now = SystemClock.uptimeMillis();
- if (mLastLoadedContacts == 0
- || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) {
- super.startDictionaryLoadingTaskLocked();
- }
- }
-
- @Override
- public void loadDictionaryAsync() {
- try {
- Cursor cursor = getContext().getContentResolver()
- .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
- if (cursor != null) {
- addWords(cursor);
- }
- } catch(IllegalStateException e) {
- Log.e(TAG, "Contacts DB is having problems");
- }
- mLastLoadedContacts = SystemClock.uptimeMillis();
- }
-
- @Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
- // Do not return bigrams from Contacts when nothing was typed.
- if (codes.size() <= 0) return;
- super.getBigrams(codes, previousWord, callback);
- }
-
- private void addWords(Cursor cursor) {
- clearDictionary();
-
- final int maxWordLength = getMaxWordLength();
- try {
- if (cursor.moveToFirst()) {
- while (!cursor.isAfterLast()) {
- String name = cursor.getString(INDEX_NAME);
-
- if (name != null && -1 == name.indexOf('@')) {
- int len = name.length();
- String prevWord = null;
-
- // TODO: Better tokenization for non-Latin writing systems
- for (int i = 0; i < len; i++) {
- if (Character.isLetter(name.charAt(i))) {
- int j;
- for (j = i + 1; j < len; j++) {
- char c = name.charAt(j);
-
- if (!(c == Keyboard.CODE_DASH
- || c == Keyboard.CODE_SINGLE_QUOTE
- || Character.isLetter(c))) {
- break;
- }
- }
-
- String word = name.substring(i, j);
- i = j - 1;
-
- // Safeguard against adding really long words. Stack
- // may overflow due to recursion
- // Also don't add single letter words, possibly confuses
- // capitalization of i.
- final int wordLen = word.length();
- if (wordLen < maxWordLength && wordLen > 1) {
- super.addWord(word, null /* shortcut */,
- FREQUENCY_FOR_CONTACTS);
- if (!TextUtils.isEmpty(prevWord)) {
- super.setBigramAndGetFrequency(prevWord, word,
- FREQUENCY_FOR_CONTACTS_BIGRAM);
- }
- prevWord = word;
- }
- }
- }
- }
- cursor.moveToNext();
- }
- }
- cursor.close();
- } catch(IllegalStateException e) {
- Log.e(TAG, "Contacts DB is having problems");
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index 7cd9bc2a8..0835450c1 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -17,6 +17,9 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
/**
* Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
@@ -28,55 +31,43 @@ public abstract class Dictionary {
*/
protected static final int FULL_WORD_SCORE_MULTIPLIER = 2;
- public static final int UNIGRAM = 0;
- public static final int BIGRAM = 1;
-
public static final int NOT_A_PROBABILITY = -1;
- /**
- * Interface to be implemented by classes requesting words to be fetched from the dictionary.
- * @see #getWords(WordComposer, CharSequence, WordCallback, ProximityInfo)
- */
- public interface WordCallback {
- /**
- * Adds a word to a list of suggestions. The word is expected to be ordered based on
- * the provided score.
- * @param word the character array containing the word
- * @param wordOffset starting offset of the word in the character array
- * @param wordLength length of valid characters in the character array
- * @param score the score of occurrence. This is normalized between 1 and 255, but
- * can exceed those limits
- * @param dicTypeId of the dictionary where word was from
- * @param dataType tells type of this data, either UNIGRAM or BIGRAM
- * @return true if the word was added, false if no more words are required
- */
- boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId,
- int dataType);
+
+ public static final String TYPE_USER_TYPED = "user_typed";
+ public static final String TYPE_APPLICATION_DEFINED = "application_defined";
+ public static final String TYPE_HARDCODED = "hardcoded"; // punctuation signs and such
+ public static final String TYPE_MAIN = "main";
+ public static final String TYPE_CONTACTS = "contacts";
+ // User dictionary, the system-managed one.
+ public static final String TYPE_USER = "user";
+ // User history dictionary internal to LatinIME.
+ public static final String TYPE_USER_HISTORY = "history";
+ public static final String TYPE_WHITELIST ="whitelist";
+ protected final String mDictType;
+
+ public Dictionary(final String dictType) {
+ mDictType = dictType;
}
/**
* Searches for words in the dictionary that match the characters in the composer. Matched
- * words are added through the callback object.
- * @param composer the key sequence to match
+ * words are returned as an ArrayList.
+ * @param composer the key sequence to match with coordinate info, as a WordComposer
* @param prevWordForBigrams the previous word, or null if none
- * @param callback the callback object to send matched words to as possible candidates
* @param proximityInfo the object for key proximity. May be ignored by some implementations.
- * @see WordCallback#addWord(char[], int, int, int, int, int)
+ * @return the list of suggestions
*/
- abstract public void getWords(final WordComposer composer,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo);
+ abstract public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo);
/**
- * Searches for pairs in the bigram dictionary that matches the previous word and all the
- * possible words following are added through the callback object.
+ * Searches for pairs in the bigram dictionary that matches the previous word.
* @param composer the key sequence to match
* @param previousWord the word before
- * @param callback the callback object to send possible word following previous word
+ * @return the list of suggestions
*/
- public void getBigrams(final WordComposer composer, final CharSequence previousWord,
- final WordCallback callback) {
- // empty base implementation
- }
+ public abstract ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+ final CharSequence previousWord);
/**
* Checks if the given word occurs in the dictionary
@@ -115,4 +106,12 @@ public abstract class Dictionary {
public void close() {
// empty base implementation
}
+
+ /**
+ * Subclasses may override to indicate that this Dictionary is not yet properly initialized.
+ */
+
+ public boolean isInitialized() {
+ return true;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 1a05fcd86..dcc53c59f 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -17,9 +17,11 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import android.util.Log;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -31,11 +33,13 @@ public class DictionaryCollection extends Dictionary {
private final String TAG = DictionaryCollection.class.getSimpleName();
protected final CopyOnWriteArrayList<Dictionary> mDictionaries;
- public DictionaryCollection() {
+ public DictionaryCollection(final String dictType) {
+ super(dictType);
mDictionaries = new CopyOnWriteArrayList<Dictionary>();
}
- public DictionaryCollection(Dictionary... dictionaries) {
+ public DictionaryCollection(final String dictType, Dictionary... dictionaries) {
+ super(dictType);
if (null == dictionaries) {
mDictionaries = new CopyOnWriteArrayList<Dictionary>();
} else {
@@ -44,23 +48,48 @@ public class DictionaryCollection extends Dictionary {
}
}
- public DictionaryCollection(Collection<Dictionary> dictionaries) {
+ public DictionaryCollection(final String dictType, Collection<Dictionary> dictionaries) {
+ super(dictType);
mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries);
mDictionaries.removeAll(Collections.singleton(null));
}
@Override
- public void getWords(final WordComposer composer, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
- for (final Dictionary dict : mDictionaries)
- dict.getWords(composer, prevWordForBigrams, callback, proximityInfo);
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer composer,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
+ final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+ if (dictionaries.isEmpty()) return null;
+ // To avoid creating unnecessary objects, we get the list out of the first
+ // dictionary and add the rest to it if not null, hence the get(0)
+ ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getWords(composer,
+ prevWordForBigrams, proximityInfo);
+ if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+ final int length = dictionaries.size();
+ for (int i = 0; i < length; ++ i) {
+ final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getWords(composer,
+ prevWordForBigrams, proximityInfo);
+ if (null != sugg) suggestions.addAll(sugg);
+ }
+ return suggestions;
}
@Override
- public void getBigrams(final WordComposer composer, final CharSequence previousWord,
- final WordCallback callback) {
- for (final Dictionary dict : mDictionaries)
- dict.getBigrams(composer, previousWord, callback);
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer composer,
+ final CharSequence previousWord) {
+ final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
+ if (dictionaries.isEmpty()) return null;
+ // To avoid creating unnecessary objects, we get the list out of the first
+ // dictionary and add the rest to it if not null, hence the get(0)
+ ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getBigrams(composer,
+ previousWord);
+ if (null == suggestions) suggestions = new ArrayList<SuggestedWordInfo>();
+ final int length = dictionaries.size();
+ for (int i = 0; i < length; ++ i) {
+ final ArrayList<SuggestedWordInfo> sugg =
+ dictionaries.get(i).getBigrams(composer, previousWord);
+ if (null != sugg) suggestions.addAll(sugg);
+ }
+ return suggestions;
}
@Override
@@ -82,8 +111,9 @@ public class DictionaryCollection extends Dictionary {
return maxFreq;
}
- public boolean isEmpty() {
- return mDictionaries.isEmpty();
+ @Override
+ public boolean isInitialized() {
+ return !mDictionaries.isEmpty();
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index a22d73af7..06a5f4b72 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -49,7 +49,8 @@ public class DictionaryFactory {
final Locale locale, final boolean useFullEditDistance) {
if (null == locale) {
Log.e(TAG, "No locale defined for dictionary");
- return new DictionaryCollection(createBinaryDictionary(context, locale));
+ return new DictionaryCollection(Dictionary.TYPE_MAIN,
+ createBinaryDictionary(context, locale));
}
final LinkedList<Dictionary> dictList = new LinkedList<Dictionary>();
@@ -59,7 +60,7 @@ public class DictionaryFactory {
for (final AssetFileAddress f : assetFileList) {
final BinaryDictionary binaryDictionary =
new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength,
- useFullEditDistance, locale);
+ useFullEditDistance, locale, Dictionary.TYPE_MAIN);
if (binaryDictionary.isValidDictionary()) {
dictList.add(binaryDictionary);
}
@@ -69,7 +70,7 @@ public class DictionaryFactory {
// If the list is empty, that means we should not use any dictionary (for example, the user
// explicitly disabled the main dictionary), so the following is okay. dictList is never
// null, but if for some reason it is, DictionaryCollection handles it gracefully.
- return new DictionaryCollection(dictList);
+ return new DictionaryCollection(Dictionary.TYPE_MAIN, dictList);
}
/**
@@ -112,7 +113,7 @@ public class DictionaryFactory {
return null;
}
return new BinaryDictionary(context, sourceDir, afd.getStartOffset(), afd.getLength(),
- false /* useFullEditDistance */, locale);
+ false /* useFullEditDistance */, locale, Dictionary.TYPE_MAIN);
} catch (android.content.res.Resources.NotFoundException e) {
Log.e(TAG, "Could not find the resource");
return null;
@@ -140,7 +141,7 @@ public class DictionaryFactory {
long startOffset, long length, final boolean useFullEditDistance, Locale locale) {
if (dictionary.isFile()) {
return new BinaryDictionary(context, dictionary.getAbsolutePath(), startOffset, length,
- useFullEditDistance, locale);
+ useFullEditDistance, locale, Dictionary.TYPE_MAIN);
} else {
Log.e(TAG, "Could not find the file. path=" + dictionary.getAbsolutePath());
return null;
diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java
deleted file mode 100644
index 0f34d50bb..000000000
--- a/java/src/com/android/inputmethod/latin/EditingUtils.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.view.inputmethod.ExtractedText;
-import android.view.inputmethod.ExtractedTextRequest;
-import android.view.inputmethod.InputConnection;
-
-import java.util.regex.Pattern;
-
-/**
- * Utility methods to deal with editing text through an InputConnection.
- */
-public class EditingUtils {
- /**
- * Number of characters we want to look back in order to identify the previous word
- */
- // Provision for a long word pair and a separator
- private static final int LOOKBACK_CHARACTER_NUM = BinaryDictionary.MAX_WORD_LENGTH * 2 + 1;
- private static final int INVALID_CURSOR_POSITION = -1;
-
- private EditingUtils() {
- // Unintentional empty constructor for singleton.
- }
-
- private static int getCursorPosition(InputConnection connection) {
- if (null == connection) return INVALID_CURSOR_POSITION;
- final ExtractedText extracted = connection.getExtractedText(new ExtractedTextRequest(), 0);
- if (extracted == null) {
- return INVALID_CURSOR_POSITION;
- }
- return extracted.startOffset + extracted.selectionStart;
- }
-
- /**
- * @param connection connection to the current text field.
- * @param separators characters which may separate words
- * @return the word that surrounds the cursor, including up to one trailing
- * separator. For example, if the field contains "he|llo world", where |
- * represents the cursor, then "hello " will be returned.
- */
- public static String getWordAtCursor(InputConnection connection, String separators) {
- // getWordRangeAtCursor returns null if the connection is null
- Range r = getWordRangeAtCursor(connection, separators);
- return (r == null) ? null : r.mWord;
- }
-
- /**
- * Represents a range of text, relative to the current cursor position.
- */
- public static class Range {
- /** Characters before selection start */
- public final int mCharsBefore;
-
- /**
- * Characters after selection start, including one trailing word
- * separator.
- */
- public final int mCharsAfter;
-
- /** The actual characters that make up a word */
- public final String mWord;
-
- public Range(int charsBefore, int charsAfter, String word) {
- if (charsBefore < 0 || charsAfter < 0) {
- throw new IndexOutOfBoundsException();
- }
- this.mCharsBefore = charsBefore;
- this.mCharsAfter = charsAfter;
- this.mWord = word;
- }
- }
-
- private static Range getWordRangeAtCursor(InputConnection connection, String sep) {
- if (connection == null || sep == null) {
- return null;
- }
- CharSequence before = connection.getTextBeforeCursor(1000, 0);
- CharSequence after = connection.getTextAfterCursor(1000, 0);
- if (before == null || after == null) {
- return null;
- }
-
- // Find first word separator before the cursor
- int start = before.length();
- while (start > 0 && !isWhitespace(before.charAt(start - 1), sep)) start--;
-
- // Find last word separator after the cursor
- int end = -1;
- while (++end < after.length() && !isWhitespace(after.charAt(end), sep)) {
- // Nothing to do here.
- }
-
- int cursor = getCursorPosition(connection);
- if (start >= 0 && cursor + end <= after.length() + before.length()) {
- String word = before.toString().substring(start, before.length())
- + after.toString().substring(0, end);
- return new Range(before.length() - start, end, word);
- }
-
- return null;
- }
-
- private static boolean isWhitespace(int code, String whitespace) {
- return whitespace.contains(String.valueOf((char) code));
- }
-
- private static final Pattern spaceRegex = Pattern.compile("\\s+");
-
- public static CharSequence getPreviousWord(InputConnection connection,
- String sentenceSeperators) {
- //TODO: Should fix this. This could be slow!
- if (null == connection) return null;
- CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
- return getPreviousWord(prev, sentenceSeperators);
- }
-
- // Get the word before the whitespace preceding the non-whitespace preceding the cursor.
- // Also, it won't return words that end in a separator.
- // Example :
- // "abc def|" -> abc
- // "abc def |" -> abc
- // "abc def. |" -> abc
- // "abc def . |" -> def
- // "abc|" -> null
- // "abc |" -> null
- // "abc. def|" -> null
- public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) {
- if (prev == null) return null;
- String[] w = spaceRegex.split(prev);
-
- // If we can't find two words, or we found an empty word, return null.
- if (w.length < 2 || w[w.length - 2].length() <= 0) return null;
-
- // If ends in a separator, return null
- char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1);
- if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
-
- return w[w.length - 2];
- }
-
- public static CharSequence getThisWord(InputConnection connection, String sentenceSeperators) {
- if (null == connection) return null;
- final CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
- return getThisWord(prev, sentenceSeperators);
- }
-
- // Get the word immediately before the cursor, even if there is whitespace between it and
- // the cursor - but not if there is punctuation.
- // Example :
- // "abc def|" -> def
- // "abc def |" -> def
- // "abc def. |" -> null
- // "abc def . |" -> null
- public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) {
- if (prev == null) return null;
- String[] w = spaceRegex.split(prev);
-
- // No word : return null
- if (w.length < 1 || w[w.length - 1].length() <= 0) return null;
-
- // If ends in a separator, return null
- char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1);
- if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
-
- return w[w.length - 1];
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c65404cbc..1cda9f257 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -19,6 +19,7 @@ import android.os.SystemClock;
import android.util.Log;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.makedict.BinaryDictInputOutput;
import com.android.inputmethod.latin.makedict.FusionDictionary;
import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
@@ -75,9 +76,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
/** The expandable fusion dictionary used to generate the binary dictionary. */
private FusionDictionary mFusionDictionary;
- /** The dictionary type id. */
- public final int mDicTypeId;
-
/**
* The name of this dictionary, used as the filename for storing the binary dictionary. Multiple
* dictionary instances with the same filename is supported, with access controlled by
@@ -123,11 +121,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
* @param context The application context of the parent.
* @param filename The filename for this binary dictionary. Multiple dictionaries with the same
* filename is supported.
- * @param dictType The type of this dictionary.
+ * @param dictType the dictionary type, as a human-readable string
*/
public ExpandableBinaryDictionary(
- final Context context, final String filename, final int dictType) {
- mDicTypeId = dictType;
+ final Context context, final String filename, final String dictType) {
+ super(dictType);
mFilename = filename;
mContext = context;
mBinaryDictionary = null;
@@ -194,46 +192,47 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
@Override
- public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
asyncReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ return getWordsInner(codes, prevWordForBigrams, proximityInfo);
}
- protected final void getWordsInner(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
// Ensure that there are no concurrent calls to getWords. If there are, do nothing and
// return.
if (mLocalDictionaryController.tryLock()) {
try {
if (mBinaryDictionary != null) {
- mBinaryDictionary.getWords(codes, prevWordForBigrams, callback, proximityInfo);
+ return mBinaryDictionary.getWords(codes, prevWordForBigrams, proximityInfo);
}
} finally {
mLocalDictionaryController.unlock();
}
}
+ return null;
}
@Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+ final CharSequence previousWord) {
asyncReloadDictionaryIfRequired();
- getBigramsInner(codes, previousWord, callback);
+ return getBigramsInner(codes, previousWord);
}
- protected void getBigramsInner(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
+ protected ArrayList<SuggestedWordInfo> getBigramsInner(final WordComposer codes,
+ final CharSequence previousWord) {
if (mLocalDictionaryController.tryLock()) {
try {
if (mBinaryDictionary != null) {
- mBinaryDictionary.getBigrams(codes, previousWord, callback);
+ return mBinaryDictionary.getBigrams(codes, previousWord);
}
} finally {
mLocalDictionaryController.unlock();
}
}
+ return null;
}
@Override
@@ -306,7 +305,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
// Build the new binary dictionary
final BinaryDictionary newBinaryDictionary =
new BinaryDictionary(mContext, filename, 0, length, true /* useFullEditDistance */,
- null);
+ null, mDictType);
if (mBinaryDictionary != null) {
// Ensure all threads accessing the current dictionary have finished before swapping in
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index 34a92fd30..76213c0da 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -21,6 +21,7 @@ import android.content.Context;
import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.UserHistoryForgettingCurveUtils.ForgettingCurveParams;
import java.util.ArrayList;
@@ -37,7 +38,6 @@ public class ExpandableDictionary extends Dictionary {
private Context mContext;
private char[] mWordBuilder = new char[BinaryDictionary.MAX_WORD_LENGTH];
- private int mDicTypeId;
private int mMaxDepth;
private int mInputLength;
@@ -151,11 +151,11 @@ public class ExpandableDictionary extends Dictionary {
private int[][] mCodes;
- public ExpandableDictionary(Context context, int dicTypeId) {
+ public ExpandableDictionary(final Context context, final String dictType) {
+ super(dictType);
mContext = context;
clearDictionary();
mCodes = new int[BinaryDictionary.MAX_WORD_LENGTH][];
- mDicTypeId = dicTypeId;
}
public void loadDictionary() {
@@ -247,27 +247,30 @@ public class ExpandableDictionary extends Dictionary {
}
@Override
- public void getWords(final WordComposer codes, final CharSequence prevWordForBigrams,
- final WordCallback callback, final ProximityInfo proximityInfo) {
+ public ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
synchronized (mUpdatingLock) {
// If we need to update, start off a background task
if (mRequiresReload) startDictionaryLoadingTaskLocked();
// Currently updating contacts, don't return any results.
- if (mUpdatingDictionary) return;
+ if (mUpdatingDictionary) return null;
}
if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) {
- return;
+ return null;
}
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ final ArrayList<SuggestedWordInfo> suggestions =
+ getWordsInner(codes, prevWordForBigrams, proximityInfo);
+ return suggestions;
}
- protected final void getWordsInner(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ protected final ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
mInputLength = codes.size();
if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
- final int[] xCoordinates = codes.getXCoordinates();
- final int[] yCoordinates = codes.getYCoordinates();
+ final InputPointers ips = codes.getInputPointers();
+ final int[] xCoordinates = ips.getXCoordinates();
+ final int[] yCoordinates = ips.getYCoordinates();
// Cache the codes so that we don't have to lookup an array list
for (int i = 0; i < mInputLength; i++) {
// TODO: Calculate proximity info here.
@@ -281,10 +284,11 @@ public class ExpandableDictionary extends Dictionary {
proximityInfo.fillArrayWithNearestKeyCodes(x, y, codes.getCodeAt(i), mCodes[i]);
}
mMaxDepth = mInputLength * 3;
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback);
+ getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, suggestions);
for (int i = 0; i < mInputLength; i++) {
- getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, callback);
+ getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, suggestions);
}
+ return suggestions;
}
@Override
@@ -368,24 +372,27 @@ public class ExpandableDictionary extends Dictionary {
* @param word the word to insert, as an array of code points
* @param depth the depth of the node in the tree
* @param finalFreq the frequency for this word
+ * @param suggestions the suggestion collection to add the suggestions to
* @return whether there is still space for more words.
- * @see Dictionary.WordCallback#addWord(char[], int, int, int, int, int)
*/
private boolean addWordAndShortcutsFromNode(final Node node, final char[] word, final int depth,
- final int finalFreq, final WordCallback callback) {
+ final int finalFreq, final ArrayList<SuggestedWordInfo> suggestions) {
if (finalFreq > 0 && !node.mShortcutOnly) {
- if (!callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, Dictionary.UNIGRAM)) {
- return false;
- }
+ // Use KIND_CORRECTION always. This dictionary does not really have a notion of
+ // COMPLETION against CORRECTION; we could artificially add one by looking at
+ // the respective size of the typed word and the suggestion if it matters sometime
+ // in the future.
+ suggestions.add(new SuggestedWordInfo(new String(word, 0, depth + 1), finalFreq,
+ SuggestedWordInfo.KIND_CORRECTION, mDictType));
+ if (suggestions.size() >= Suggest.MAX_SUGGESTIONS) return false;
}
if (null != node.mShortcutTargets) {
final int length = node.mShortcutTargets.size();
for (int shortcutIndex = 0; shortcutIndex < length; ++shortcutIndex) {
final char[] shortcut = node.mShortcutTargets.get(shortcutIndex);
- if (!callback.addWord(shortcut, 0, shortcut.length, finalFreq, mDicTypeId,
- Dictionary.UNIGRAM)) {
- return false;
- }
+ suggestions.add(new SuggestedWordInfo(new String(shortcut, 0, shortcut.length),
+ finalFreq, SuggestedWordInfo.KIND_SHORTCUT, mDictType));
+ if (suggestions.size() > Suggest.MAX_SUGGESTIONS) return false;
}
}
return true;
@@ -408,12 +415,12 @@ public class ExpandableDictionary extends Dictionary {
* case we skip over some punctuations such as apostrophe in the traversal. That is, if you type
* "wouldve", it could be matching "would've", so the depth will be one more than the
* inputIndex
- * @param callback the callback class for adding a word
+ * @param suggestions the list in which to add suggestions
*/
// TODO: Share this routine with the native code for BinaryDictionary
protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word,
final int depth, final boolean completion, int snr, int inputIndex, int skipPos,
- WordCallback callback) {
+ final ArrayList<SuggestedWordInfo> suggestions) {
final int count = roots.mLength;
final int codeSize = mInputLength;
// Optimization: Prune out words that are too long compared to how much was typed.
@@ -443,14 +450,14 @@ public class ExpandableDictionary extends Dictionary {
} else {
finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength);
}
- if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, callback)) {
+ if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, suggestions)) {
// No space left in the queue, bail out
return;
}
}
if (children != null) {
getWordsRec(children, codes, word, depth + 1, true, snr, inputIndex,
- skipPos, callback);
+ skipPos, suggestions);
}
} else if ((c == Keyboard.CODE_SINGLE_QUOTE
&& currentChars[0] != Keyboard.CODE_SINGLE_QUOTE) || depth == skipPos) {
@@ -458,7 +465,7 @@ public class ExpandableDictionary extends Dictionary {
word[depth] = c;
if (children != null) {
getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex,
- skipPos, callback);
+ skipPos, suggestions);
}
} else {
// Don't use alternatives if we're looking for missing characters
@@ -483,7 +490,7 @@ public class ExpandableDictionary extends Dictionary {
snr * addedAttenuation, mInputLength);
}
if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq,
- callback)) {
+ suggestions)) {
// No space left in the queue, bail out
return;
}
@@ -491,12 +498,12 @@ public class ExpandableDictionary extends Dictionary {
if (children != null) {
getWordsRec(children, codes, word, depth + 1,
true, snr * addedAttenuation, inputIndex + 1,
- skipPos, callback);
+ skipPos, suggestions);
}
} else if (children != null) {
getWordsRec(children, codes, word, depth + 1,
false, snr * addedAttenuation, inputIndex + 1,
- skipPos, callback);
+ skipPos, suggestions);
}
}
}
@@ -514,8 +521,10 @@ public class ExpandableDictionary extends Dictionary {
/**
* Adds bigrams to the in-memory trie structure that is being used to retrieve any word
+ * @param word1 the first word of this bigram
+ * @param word2 the second word of this bigram
* @param frequency frequency for this bigram
- * @param addFrequency if true, it adds to current frequency, else it overwrites the old value
+ * @param fcp an instance of ForgettingCurveParams to use for decay policy
* @return returns the final bigram frequency
*/
private int setBigramAndGetFrequency(
@@ -591,22 +600,25 @@ public class ExpandableDictionary extends Dictionary {
}
private void runBigramReverseLookUp(final CharSequence previousWord,
- final WordCallback callback) {
+ final ArrayList<SuggestedWordInfo> suggestions) {
// Search for the lowercase version of the word only, because that's where bigrams
// store their sons.
Node prevWord = searchNode(mRoots, previousWord.toString().toLowerCase(), 0,
previousWord.length());
if (prevWord != null && prevWord.mNGrams != null) {
- reverseLookUp(prevWord.mNGrams, callback);
+ reverseLookUp(prevWord.mNGrams, suggestions);
}
}
@Override
- public void getBigrams(final WordComposer codes, final CharSequence previousWord,
- final WordCallback callback) {
+ public ArrayList<SuggestedWordInfo> getBigrams(final WordComposer codes,
+ final CharSequence previousWord) {
if (!reloadDictionaryIfRequired()) {
- runBigramReverseLookUp(previousWord, callback);
+ final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
+ runBigramReverseLookUp(previousWord, suggestions);
+ return suggestions;
}
+ return null;
}
/**
@@ -633,11 +645,12 @@ public class ExpandableDictionary extends Dictionary {
/**
* reverseLookUp retrieves the full word given a list of terminal nodes and adds those words
- * through callback.
+ * to the suggestions list passed as an argument.
* @param terminalNodes list of terminal nodes we want to add
+ * @param suggestions the suggestion collection to add the word to
*/
private void reverseLookUp(LinkedList<NextWord> terminalNodes,
- final WordCallback callback) {
+ final ArrayList<SuggestedWordInfo> suggestions) {
Node node;
int freq;
for (NextWord nextWord : terminalNodes) {
@@ -651,8 +664,9 @@ public class ExpandableDictionary extends Dictionary {
} while (node != null);
if (freq >= 0) {
- callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index,
- freq, mDicTypeId, Dictionary.BIGRAM);
+ suggestions.add(new SuggestedWordInfo(new String(mLookedUpString, index,
+ BinaryDictionary.MAX_WORD_LENGTH - index),
+ freq, SuggestedWordInfo.KIND_CORRECTION, mDictType));
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java
new file mode 100644
index 000000000..218243e9f
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/InputPointers.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import java.util.Arrays;
+
+public class InputPointers {
+ private final ScalableIntArray mXCoordinates = new ScalableIntArray();
+ private final ScalableIntArray mYCoordinates = new ScalableIntArray();
+ private final ScalableIntArray mPointerIds = new ScalableIntArray();
+ private final ScalableIntArray mTimes = new ScalableIntArray();
+
+ public void addPointer(int index, int x, int y, int pointerId, int time) {
+ mXCoordinates.add(index, x);
+ mYCoordinates.add(index, y);
+ mPointerIds.add(index, pointerId);
+ mTimes.add(index, time);
+ }
+
+ public void addPointer(int x, int y, int pointerId, int time) {
+ mXCoordinates.add(x);
+ mYCoordinates.add(y);
+ mPointerIds.add(pointerId);
+ mTimes.add(time);
+ }
+
+ public void set(InputPointers ip) {
+ mXCoordinates.set(ip.mXCoordinates);
+ mYCoordinates.set(ip.mYCoordinates);
+ mPointerIds.set(ip.mPointerIds);
+ mTimes.set(ip.mTimes);
+ }
+
+ public void copy(InputPointers ip) {
+ mXCoordinates.copy(ip.mXCoordinates);
+ mYCoordinates.copy(ip.mYCoordinates);
+ mPointerIds.copy(ip.mPointerIds);
+ mTimes.copy(ip.mTimes);
+ }
+
+ public void reset() {
+ mXCoordinates.reset();
+ mYCoordinates.reset();
+ mPointerIds.reset();
+ mTimes.reset();
+ }
+
+ public int getPointerSize() {
+ return mXCoordinates.getLength();
+ }
+
+ public int[] getXCoordinates() {
+ return mXCoordinates.mArray;
+ }
+
+ public int[] getYCoordinates() {
+ return mYCoordinates.mArray;
+ }
+
+ public int[] getPointerIds() {
+ return mPointerIds.mArray;
+ }
+
+ public int[] getTimes() {
+ return mTimes.mArray;
+ }
+
+ private static class ScalableIntArray {
+ private static final int DEFAULT_SIZE = BinaryDictionary.MAX_WORD_LENGTH;
+ private int[] mArray;
+ private int mLength;
+
+ public ScalableIntArray() {
+ reset();
+ }
+
+ public void add(int index, int val) {
+ if (mLength < index + 1) {
+ mLength = index;
+ add(val);
+ } else {
+ mArray[index] = val;
+ }
+ }
+
+ public void add(int val) {
+ if (mLength >= mArray.length) {
+ final int[] newArray = new int[mLength * 2];
+ System.arraycopy(mArray, 0, newArray, 0, mLength);
+ }
+ mArray[mLength] = val;
+ ++mLength;
+ }
+
+ public int getLength() {
+ return mLength;
+ }
+
+ public void reset() {
+ mArray = new int[DEFAULT_SIZE];
+ mLength = 0;
+ }
+
+ public int[] getPrimitiveArray() {
+ return mArray;
+ }
+
+ public void copy(ScalableIntArray ip) {
+ mArray = Arrays.copyOf(ip.mArray, ip.mArray.length);
+ }
+
+ public void set(ScalableIntArray ip) {
+ mArray = ip.mArray;
+ mLength = ip.mLength;
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index 4e1f5fe92..318aecb50 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -41,26 +41,26 @@ public class LastComposedWord {
public static final int NOT_A_SEPARATOR = -1;
public final int[] mPrimaryKeyCodes;
- public final int[] mXCoordinates;
- public final int[] mYCoordinates;
public final String mTypedWord;
public final String mCommittedWord;
public final int mSeparatorCode;
public final CharSequence mPrevWord;
+ public final InputPointers mInputPointers = new InputPointers();
private boolean mActive;
public static final LastComposedWord NOT_A_COMPOSED_WORD =
- new LastComposedWord(null, null, null, "", "", NOT_A_SEPARATOR, null);
+ new LastComposedWord(null, null, "", "", NOT_A_SEPARATOR, null);
// Warning: this is using the passed objects as is and fully expects them to be
// immutable. Do not fiddle with their contents after you passed them to this constructor.
- public LastComposedWord(final int[] primaryKeyCodes, final int[] xCoordinates,
- final int[] yCoordinates, final String typedWord, final String committedWord,
+ public LastComposedWord(final int[] primaryKeyCodes, final InputPointers inputPointers,
+ final String typedWord, final String committedWord,
final int separatorCode, final CharSequence prevWord) {
mPrimaryKeyCodes = primaryKeyCodes;
- mXCoordinates = xCoordinates;
- mYCoordinates = yCoordinates;
+ if (inputPointers != null) {
+ mInputPointers.copy(inputPointers);
+ }
mTypedWord = typedWord;
mCommittedWord = committedWord;
mSeparatorCode = separatorCode;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 97e898af9..e7f547812 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -56,7 +56,6 @@ import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.accessibility.AccessibilityUtils;
@@ -103,27 +102,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
*/
private static final String SCHEME_PACKAGE = "package";
- /** Whether to use the binary version of the contacts dictionary */
- public static final boolean USE_BINARY_CONTACTS_DICTIONARY = true;
-
- /** Whether to use the binary version of the user dictionary */
- public static final boolean USE_BINARY_USER_DICTIONARY = true;
-
- // TODO: migrate this to SettingsValues
- private int mSuggestionVisibility;
- private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE
- = R.string.prefs_suggestion_visibility_show_value;
- private static final int SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE
- = R.string.prefs_suggestion_visibility_show_only_portrait_value;
- private static final int SUGGESTION_VISIBILILTY_HIDE_VALUE
- = R.string.prefs_suggestion_visibility_hide_value;
-
- private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] {
- SUGGESTION_VISIBILILTY_SHOW_VALUE,
- SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE,
- SUGGESTION_VISIBILILTY_HIDE_VALUE
- };
-
private static final int SPACE_STATE_NONE = 0;
// Double space: the state where the user pressed space twice quickly, which LatinIME
// resolved as period-space. Undoing this converts the period to a space.
@@ -143,8 +121,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Current space state of the input method. This can be any of the above constants.
private int mSpaceState;
- private SettingsValues mSettingsValues;
- private InputAttributes mInputAttributes;
+ private SettingsValues mCurrentSettings;
private View mExtractArea;
private View mKeyPreviewBackingView;
@@ -162,15 +139,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private boolean mShouldSwitchToLastSubtype = true;
private boolean mIsMainDictionaryAvailable;
- // TODO: revert this back to the concrete class after transition.
- private Dictionary mUserDictionary;
+ private UserBinaryDictionary mUserDictionary;
private UserHistoryDictionary mUserHistoryDictionary;
private boolean mIsUserDictionaryAvailable;
private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
private WordComposer mWordComposer = new WordComposer();
-
- private int mCorrectionMode;
+ private RichInputConnection mConnection = new RichInputConnection();
// Keep track of the last selection range to decide if we need to show word alternatives
private static final int NOT_A_CURSOR_POSITION = -1;
@@ -203,7 +178,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
private static final int MSG_UPDATE_SHIFT_STATE = 1;
- private static final int MSG_SPACE_TYPED = 4;
private static final int MSG_SET_BIGRAM_PREDICTIONS = 5;
private static final int MSG_PENDING_IMS_CALLBACK = 6;
private static final int MSG_UPDATE_SUGGESTIONS = 7;
@@ -211,6 +185,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private int mDelayUpdateSuggestions;
private int mDelayUpdateShiftState;
private long mDoubleSpacesTurnIntoPeriodTimeout;
+ private long mDoubleSpaceTimerStart;
public UIHandler(LatinIME outerInstance) {
super(outerInstance);
@@ -275,16 +250,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public void startDoubleSpacesTimer() {
- removeMessages(MSG_SPACE_TYPED);
- sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout);
+ mDoubleSpaceTimerStart = SystemClock.uptimeMillis();
}
public void cancelDoubleSpacesTimer() {
- removeMessages(MSG_SPACE_TYPED);
+ mDoubleSpaceTimerStart = 0;
}
public boolean isAcceptingDoubleSpaces() {
- return hasMessages(MSG_SPACE_TYPED);
+ return SystemClock.uptimeMillis() - mDoubleSpaceTimerStart
+ < mDoubleSpacesTurnIntoPeriodTimeout;
}
// Working variables for the following methods.
@@ -393,7 +368,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mPrefs = prefs;
LatinImeLogger.init(this, prefs);
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.init(this, prefs);
+ ResearchLogger.getInstance().init(this, prefs);
}
InputMethodManagerCompatWrapper.init(this);
SubtypeSwitcher.init(this);
@@ -411,14 +386,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
loadSettings();
- ImfUtils.setAdditionalInputMethodSubtypes(this, mSettingsValues.getAdditionalSubtypes());
-
- // TODO: remove the following when it's not needed by updateCorrectionMode() any more
- mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
- updateCorrectionMode();
+ ImfUtils.setAdditionalInputMethodSubtypes(this, mCurrentSettings.getAdditionalSubtypes());
Utils.GCUtils.getInstance().reset();
boolean tryGC = true;
+ // Shouldn't this be removed? I think that from Honeycomb on, the GC is now actually working
+ // as expected and this code is useless.
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
try {
initSuggest();
@@ -454,14 +427,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
// is not guaranteed. It may even be called at the same time on a different thread.
if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
+ final InputAttributes inputAttributes =
+ new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode());
final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
@Override
protected SettingsValues job(Resources res) {
- return new SettingsValues(mPrefs, LatinIME.this);
+ return new SettingsValues(mPrefs, inputAttributes, LatinIME.this);
}
};
- mSettingsValues = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale());
- mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues);
+ mCurrentSettings = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale());
+ mFeedbackManager = new AudioAndHapticFeedbackManager(this, mCurrentSettings);
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
}
@@ -469,7 +444,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
final String localeStr = subtypeLocale.toString();
- final Dictionary oldContactsDictionary;
+ final ContactsBinaryDictionary oldContactsDictionary;
if (mSuggest != null) {
oldContactsDictionary = mSuggest.getContactsDictionary();
mSuggest.close();
@@ -477,19 +452,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
oldContactsDictionary = null;
}
mSuggest = new Suggest(this, subtypeLocale);
- if (mSettingsValues.mAutoCorrectEnabled) {
- mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
+ if (mCurrentSettings.mCorrectionEnabled) {
+ mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
}
mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
-
- if (USE_BINARY_USER_DICTIONARY) {
- mUserDictionary = new UserBinaryDictionary(this, localeStr);
- mIsUserDictionaryAvailable = ((UserBinaryDictionary)mUserDictionary).isEnabled();
- } else {
- mUserDictionary = new UserDictionary(this, localeStr);
- mIsUserDictionaryAvailable = ((UserDictionary)mUserDictionary).isEnabled();
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().initSuggest(mSuggest);
}
+
+ mUserDictionary = new UserBinaryDictionary(this, localeStr);
+ mIsUserDictionaryAvailable = mUserDictionary.isEnabled();
mSuggest.setUserDictionary(mUserDictionary);
resetContactsDictionary(oldContactsDictionary);
@@ -497,44 +470,43 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
// is not guaranteed. It may even be called at the same time on a different thread.
if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- mUserHistoryDictionary = UserHistoryDictionary.getInstance(
- this, localeStr, Suggest.DIC_USER_HISTORY, mPrefs);
+ mUserHistoryDictionary = UserHistoryDictionary.getInstance(this, localeStr, mPrefs);
mSuggest.setUserHistoryDictionary(mUserHistoryDictionary);
}
/**
* Resets the contacts dictionary in mSuggest according to the user settings.
*
- * This method takes an optional contacts dictionary to use. Since the contacts dictionary
- * does not depend on the locale, it can be reused across different instances of Suggest.
- * The dictionary will also be opened or closed as necessary depending on the settings.
+ * This method takes an optional contacts dictionary to use when the locale hasn't changed
+ * since the contacts dictionary can be opened or closed as necessary depending on the settings.
*
* @param oldContactsDictionary an optional dictionary to use, or null
*/
- private void resetContactsDictionary(final Dictionary oldContactsDictionary) {
- final boolean shouldSetDictionary = (null != mSuggest && mSettingsValues.mUseContactsDict);
+ private void resetContactsDictionary(final ContactsBinaryDictionary oldContactsDictionary) {
+ final boolean shouldSetDictionary = (null != mSuggest && mCurrentSettings.mUseContactsDict);
- final Dictionary dictionaryToUse;
+ final ContactsBinaryDictionary dictionaryToUse;
if (!shouldSetDictionary) {
// Make sure the dictionary is closed. If it is already closed, this is a no-op,
// so it's safe to call it anyways.
if (null != oldContactsDictionary) oldContactsDictionary.close();
dictionaryToUse = null;
- } else if (null != oldContactsDictionary) {
- // Make sure the old contacts dictionary is opened. If it is already open, this is a
- // no-op, so it's safe to call it anyways.
- if (USE_BINARY_CONTACTS_DICTIONARY) {
- ((ContactsBinaryDictionary)oldContactsDictionary).reopen(this);
- } else {
- ((ContactsDictionary)oldContactsDictionary).reopen(this);
- }
- dictionaryToUse = oldContactsDictionary;
} else {
- if (USE_BINARY_CONTACTS_DICTIONARY) {
- dictionaryToUse = new ContactsBinaryDictionary(this, Suggest.DIC_CONTACTS,
- mSubtypeSwitcher.getCurrentSubtypeLocale());
+ final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ if (null != oldContactsDictionary) {
+ if (!oldContactsDictionary.mLocale.equals(locale)) {
+ // If the locale has changed then recreate the contacts dictionary. This
+ // allows locale dependent rules for handling bigram name predictions.
+ oldContactsDictionary.close();
+ dictionaryToUse = new ContactsBinaryDictionary(this, locale);
+ } else {
+ // Make sure the old contacts dictionary is opened. If it is already open,
+ // this is a no-op, so it's safe to call it anyways.
+ oldContactsDictionary.reopen(this);
+ dictionaryToUse = oldContactsDictionary;
+ }
} else {
- dictionaryToUse = new ContactsDictionary(this, Suggest.DIC_CONTACTS);
+ dictionaryToUse = new ContactsBinaryDictionary(this, locale);
}
}
@@ -569,9 +541,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mDisplayOrientation != conf.orientation) {
mDisplayOrientation = conf.orientation;
mHandler.startOrientationChanging();
- final InputConnection ic = getCurrentInputConnection();
- commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR);
- if (ic != null) ic.finishComposingText(); // For voice input
+ mConnection.beginBatchEdit(getCurrentInputConnection());
+ commitTyped(LastComposedWord.NOT_A_SEPARATOR);
+ mConnection.finishComposingText();
+ mConnection.endBatchEdit();
if (isShowingOptionDialog())
mOptionsDialog.dismiss();
}
@@ -660,6 +633,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0));
}
if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().start();
ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs);
}
if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
@@ -699,7 +673,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
updateFullscreenMode();
mLastSelectionStart = editorInfo.initialSelStart;
mLastSelectionEnd = editorInfo.initialSelEnd;
- mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode());
mApplicationSpecifiedCompletions = null;
inputView.closing();
@@ -709,14 +682,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSpaceState = SPACE_STATE_NONE;
loadSettings();
- updateCorrectionMode();
- updateSuggestionVisibility(mResources);
- if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) {
- mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
+ if (mSuggest != null && mCurrentSettings.mCorrectionEnabled) {
+ mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
}
- switcher.loadKeyboard(editorInfo, mSettingsValues);
+ switcher.loadKeyboard(editorInfo, mCurrentSettings);
if (mSuggestionsView != null)
mSuggestionsView.clear();
@@ -726,19 +697,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.postUpdateSuggestions();
mHandler.cancelDoubleSpacesTimer();
- inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn,
- mSettingsValues.mKeyPreviewPopupDismissDelay);
+ inputView.setKeyPreviewPopupEnabled(mCurrentSettings.mKeyPreviewPopupOn,
+ mCurrentSettings.mKeyPreviewPopupDismissDelay);
inputView.setProximityCorrectionEnabled(true);
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
+ @Override
public void onTargetApplicationKnown(final ApplicationInfo info) {
mTargetApplicationInfo = info;
}
@Override
public void onWindowHidden() {
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_onWindowHidden(mLastSelectionStart, mLastSelectionEnd,
+ getCurrentInputConnection());
+ }
super.onWindowHidden();
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.closing();
@@ -748,6 +724,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
super.onFinishInput();
LatinImeLogger.commit();
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().stop();
+ }
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.closing();
@@ -768,7 +747,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
int composingSpanStart, int composingSpanEnd) {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
composingSpanStart, composingSpanEnd);
-
if (DEBUG) {
Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
+ ", ose=" + oldSelEnd
@@ -780,9 +758,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ ", ce=" + composingSpanEnd);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
+ final boolean expectingUpdateSelectionFromLogger =
+ ResearchLogger.getAndClearLatinIMEExpectingUpdateSelection();
ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd,
oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart,
- composingSpanEnd);
+ composingSpanEnd, mExpectingUpdateSelection,
+ expectingUpdateSelectionFromLogger, mConnection);
+ if (expectingUpdateSelectionFromLogger) {
+ // TODO: Investigate. Quitting now sounds wrong - we won't do the resetting work
+ return;
+ }
}
// TODO: refactor the following code to be less contrived.
@@ -841,7 +826,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
*/
@Override
public void onExtractedTextClicked() {
- if (isSuggestionsRequested()) return;
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) return;
super.onExtractedTextClicked();
}
@@ -857,7 +842,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
*/
@Override
public void onExtractedCursorMovement(int dx, int dy) {
- if (isSuggestionsRequested()) return;
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) return;
super.onExtractedCursorMovement(dx, dy);
}
@@ -888,33 +873,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
}
- if (mInputAttributes.mApplicationSpecifiedCompletionOn) {
- mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
- if (applicationSpecifiedCompletions == null) {
- clearSuggestions();
- return;
- }
-
- final ArrayList<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords =
- SuggestedWords.getFromApplicationSpecifiedCompletions(
- applicationSpecifiedCompletions);
- final SuggestedWords suggestedWords = new SuggestedWords(
- applicationSuggestedWords,
- false /* typedWordValid */,
- false /* hasAutoCorrectionCandidate */,
- false /* allowsToBeAutoCorrected */,
- false /* isPunctuationSuggestions */,
- false /* isObsoleteSuggestions */,
- false /* isPrediction */);
- // When in fullscreen mode, show completions generated by the application
- final boolean isAutoCorrection = false;
- setSuggestions(suggestedWords, isAutoCorrection);
- setAutoCorrectionIndicator(isAutoCorrection);
- // TODO: is this the right thing to do? What should we auto-correct to in
- // this case? This says to keep whatever the user typed.
- mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
- setSuggestionStripShown(true);
+ if (!mCurrentSettings.isApplicationSpecifiedCompletionsOn()) return;
+ mApplicationSpecifiedCompletions = applicationSpecifiedCompletions;
+ if (applicationSpecifiedCompletions == null) {
+ clearSuggestions();
+ return;
}
+
+ final ArrayList<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords =
+ SuggestedWords.getFromApplicationSpecifiedCompletions(
+ applicationSpecifiedCompletions);
+ final SuggestedWords suggestedWords = new SuggestedWords(
+ applicationSuggestedWords,
+ false /* typedWordValid */,
+ false /* hasAutoCorrectionCandidate */,
+ false /* isPunctuationSuggestions */,
+ false /* isObsoleteSuggestions */,
+ false /* isPrediction */);
+ // When in fullscreen mode, show completions generated by the application
+ final boolean isAutoCorrection = false;
+ setSuggestions(suggestedWords, isAutoCorrection);
+ setAutoCorrectionIndicator(isAutoCorrection);
+ // TODO: is this the right thing to do? What should we auto-correct to in
+ // this case? This says to keep whatever the user typed.
+ mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
+ setSuggestionStripShown(true);
}
private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) {
@@ -1001,7 +984,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public boolean onEvaluateFullscreenMode() {
// Reread resource value here, because this method is called by framework anytime as needed.
final boolean isFullscreenModeAllowed =
- mSettingsValues.isFullscreenModeAllowed(getResources());
+ mCurrentSettings.isFullscreenModeAllowed(getResources());
return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed;
}
@@ -1016,15 +999,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// This will reset the whole input state to the starting state. It will clear
- // the composing word, reset the last composed word, tell the inputconnection
- // and the composingStateManager about it.
+ // the composing word, reset the last composed word, tell the inputconnection about it.
private void resetEntireInputState() {
resetComposingState(true /* alsoResetLastComposedWord */);
updateSuggestions();
- final InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.finishComposingText();
- }
+ mConnection.finishComposingText();
}
private void resetComposingState(final boolean alsoResetLastComposedWord) {
@@ -1033,15 +1012,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
}
- public void commitTyped(final InputConnection ic, final int separatorCode) {
+ public void commitTyped(final int separatorCode) {
if (!mWordComposer.isComposingWord()) return;
final CharSequence typedWord = mWordComposer.getTypedWord();
if (typedWord.length() > 0) {
- if (ic != null) {
- ic.commitText(typedWord, 1);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_commitText(typedWord);
- }
+ mConnection.commitText(typedWord, 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_commitText(typedWord);
}
final CharSequence prevWord = addToUserHistoryDictionary(typedWord);
mLastComposedWord = mWordComposer.commitWord(
@@ -1052,7 +1029,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public int getCurrentAutoCapsState() {
- if (!mSettingsValues.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
+ if (!mCurrentSettings.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
final EditorInfo ei = getCurrentInputEditorInfo();
if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
@@ -1070,27 +1047,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// unless needed.
if (mWordComposer.isComposingWord()) return Constants.TextUtils.CAP_MODE_OFF;
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return Constants.TextUtils.CAP_MODE_OFF;
// TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls.
// Note: getCursorCapsMode() returns the current capitalization mode that is any
// combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none
// of them.
- return ic.getCursorCapsMode(inputType);
+ return mConnection.getCursorCapsMode(inputType);
}
- // "ic" may be null
- private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) {
- if (null == ic) return;
- CharSequence lastTwo = ic.getTextBeforeCursor(2, 0);
+ private void swapSwapperAndSpace() {
+ CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0);
// It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
if (lastTwo != null && lastTwo.length() == 2
&& lastTwo.charAt(0) == Keyboard.CODE_SPACE) {
- ic.deleteSurroundingText(2, 0);
+ mConnection.deleteSurroundingText(2, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(2);
}
- ic.commitText(lastTwo.charAt(1) + " ", 1);
+ mConnection.commitText(lastTwo.charAt(1) + " ", 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_swapSwapperAndSpaceWhileInBatchEdit();
}
@@ -1098,18 +1071,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) {
- if (mCorrectionMode == Suggest.CORRECTION_NONE) return false;
- if (ic == null) return false;
- final CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
+ private boolean maybeDoubleSpace() {
+ if (!mCurrentSettings.mCorrectionEnabled) return false;
+ if (!mHandler.isAcceptingDoubleSpaces()) return false;
+ final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0);
if (lastThree != null && lastThree.length() == 3
&& canBeFollowedByPeriod(lastThree.charAt(0))
&& lastThree.charAt(1) == Keyboard.CODE_SPACE
- && lastThree.charAt(2) == Keyboard.CODE_SPACE
- && mHandler.isAcceptingDoubleSpaces()) {
+ && lastThree.charAt(2) == Keyboard.CODE_SPACE) {
mHandler.cancelDoubleSpacesTimer();
- ic.deleteSurroundingText(2, 0);
- ic.commitText(". ", 1);
+ mConnection.deleteSurroundingText(2, 0);
+ mConnection.commitText(". ", 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_doubleSpaceAutoPeriod();
}
@@ -1131,26 +1103,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|| codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET;
}
- // "ic" may be null
- private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) {
- if (ic == null) return;
- final CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
- if (lastOne != null && lastOne.length() == 1
- && lastOne.charAt(0) == Keyboard.CODE_SPACE) {
- ic.deleteSurroundingText(1, 0);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_deleteSurroundingText(1);
- }
- }
- }
-
@Override
public boolean addWordToDictionary(String word) {
- if (USE_BINARY_USER_DICTIONARY) {
- ((UserBinaryDictionary)mUserDictionary).addWordToUserDictionary(word, 128);
- } else {
- ((UserDictionary)mUserDictionary).addWordToUserDictionary(word, 128);
- }
+ mUserDictionary.addWordToUserDictionary(word, 128);
// Suggestion strip should be updated after the operation of adding word to the
// user dictionary
mHandler.postUpdateSuggestions();
@@ -1193,17 +1148,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void performEditorAction(int actionId) {
- final InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.performEditorAction(actionId);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_performEditorAction(actionId);
- }
+ mConnection.performEditorAction(actionId);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_performEditorAction(actionId);
}
}
private void handleLanguageSwitchKey() {
- final boolean includesOtherImes = mSettingsValues.mIncludesOtherImesInLanguageSwitchList;
+ final boolean includesOtherImes = mCurrentSettings.mIncludesOtherImesInLanguageSwitchList;
final IBinder token = getWindow().getWindow().getAttributes().token;
if (mShouldSwitchToLastSubtype) {
final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype();
@@ -1221,12 +1173,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- static private void sendUpDownEnterOrBackspace(final int code, final InputConnection ic) {
+ private void sendUpDownEnterOrBackspace(final int code) {
final long eventTime = SystemClock.uptimeMillis();
- ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
+ mConnection.sendKeyEvent(new KeyEvent(eventTime, eventTime,
KeyEvent.ACTION_DOWN, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
- ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+ mConnection.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
KeyEvent.ACTION_UP, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
}
@@ -1239,24 +1191,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
- final InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
- // we want to be able to compile against the Ice Cream Sandwich SDK.
- if (Keyboard.CODE_ENTER == code && mTargetApplicationInfo != null
- && mTargetApplicationInfo.targetSdkVersion < 16) {
- // Backward compatibility mode. Before Jelly bean, the keyboard would simulate
- // a hardware keyboard event on pressing enter or delete. This is bad for many
- // reasons (there are race conditions with commits) but some applications are
- // relying on this behavior so we continue to support it for older apps.
- sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_ENTER, ic);
- } else {
- final String text = new String(new int[] { code }, 0, 1);
- ic.commitText(text, text.length());
- }
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_sendKeyCodePoint(code);
- }
+ // 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
+ // we want to be able to compile against the Ice Cream Sandwich SDK.
+ if (Keyboard.CODE_ENTER == code && mTargetApplicationInfo != null
+ && mTargetApplicationInfo.targetSdkVersion < 16) {
+ // Backward compatibility mode. Before Jelly bean, the keyboard would simulate
+ // a hardware keyboard event on pressing enter or delete. This is bad for many
+ // reasons (there are race conditions with commits) but some applications are
+ // relying on this behavior so we continue to support it for older apps.
+ sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_ENTER);
+ } else {
+ final String text = new String(new int[] { code }, 0, 1);
+ mConnection.commitText(text, text.length());
+ }
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_sendKeyCodePoint(code);
}
}
@@ -1268,11 +1217,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mDeleteCount = 0;
}
mLastKeyTime = when;
+ mConnection.beginBatchEdit(getCurrentInputConnection());
if (ProductionFlag.IS_EXPERIMENTAL) {
- if (ResearchLogger.sIsLogging) {
- ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y);
- }
+ ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
}
final KeyboardSwitcher switcher = mKeyboardSwitcher;
@@ -1321,14 +1269,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
case Keyboard.CODE_LANGUAGE_SWITCH:
handleLanguageSwitchKey();
break;
+ case Keyboard.CODE_RESEARCH:
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.getInstance().presentResearchDialog(this);
+ }
+ break;
default:
- if (primaryCode == Keyboard.CODE_TAB
- && mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT) {
+ if (primaryCode == Keyboard.CODE_TAB && mCurrentSettings.isEditorActionNext()) {
performEditorAction(EditorInfo.IME_ACTION_NEXT);
break;
}
mSpaceState = SPACE_STATE_NONE;
- if (mSettingsValues.isWordSeparator(primaryCode)) {
+ if (mCurrentSettings.isWordSeparator(primaryCode)) {
didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
} else {
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
@@ -1349,23 +1301,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
&& primaryCode != Keyboard.CODE_SWITCH_ALPHA_SYMBOL)
mLastComposedWord.deactivate();
mEnteredText = null;
+ mConnection.endBatchEdit();
}
@Override
public void onTextInput(CharSequence text) {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- ic.beginBatchEdit();
- commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR);
- text = specificTldProcessingOnTextInput(ic, text);
+ mConnection.beginBatchEdit(getCurrentInputConnection());
+ commitTyped(LastComposedWord.NOT_A_SEPARATOR);
+ text = specificTldProcessingOnTextInput(text);
if (SPACE_STATE_PHANTOM == mSpaceState) {
sendKeyCodePoint(Keyboard.CODE_SPACE);
}
- ic.commitText(text, 1);
+ mConnection.commitText(text, 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_commitText(text);
}
- ic.endBatchEdit();
+ mConnection.endBatchEdit();
mKeyboardSwitcher.updateShiftState();
mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT);
mSpaceState = SPACE_STATE_NONE;
@@ -1373,9 +1324,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
resetComposingState(true /* alsoResetLastComposedWord */);
}
- // ic may not be null
- private CharSequence specificTldProcessingOnTextInput(final InputConnection ic,
- final CharSequence text) {
+ private CharSequence specificTldProcessingOnTextInput(final CharSequence text) {
if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD
|| !Character.isLetter(text.charAt(1))) {
// Not a tld: do nothing.
@@ -1384,7 +1333,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// We have a TLD (or something that looks like this): make sure we don't add
// a space even if currently in phantom mode.
mSpaceState = SPACE_STATE_NONE;
- final CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
+ final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0);
if (lastOne != null && lastOne.length() == 1
&& lastOne.charAt(0) == Keyboard.CODE_PERIOD) {
return text.subSequence(1, text.length());
@@ -1400,24 +1349,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void handleBackspace(final int spaceState) {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
- ic.beginBatchEdit();
- handleBackspaceWhileInBatchEdit(spaceState, ic);
- ic.endBatchEdit();
- }
-
- // "ic" may not be null.
- private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) {
// In many cases, we may have to put the keyboard in auto-shift state again.
mHandler.postUpdateShiftState();
- if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) {
+ if (mEnteredText != null && mConnection.sameAsTextBeforeCursor(mEnteredText)) {
// Cancel multi-character input: remove the text we just entered.
// This is triggered on backspace after a key that inputs multiple characters,
// like the smiley key or the .com key.
final int length = mEnteredText.length();
- ic.deleteSurroundingText(length, 0);
+ mConnection.deleteSurroundingText(length, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(length);
}
@@ -1431,7 +1371,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final int length = mWordComposer.size();
if (length > 0) {
mWordComposer.deleteLast();
- ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
+ mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
// If we have deleted the last remaining character of a word, then we are not
// isComposingWord() any more.
if (!mWordComposer.isComposingWord()) {
@@ -1442,7 +1382,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.postUpdateSuggestions();
}
} else {
- ic.deleteSurroundingText(1, 0);
+ mConnection.deleteSurroundingText(1, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
@@ -1450,17 +1390,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
if (mLastComposedWord.canRevertCommit()) {
Utils.Stats.onAutoCorrectionCancellation();
- revertCommit(ic);
+ revertCommit();
return;
}
if (SPACE_STATE_DOUBLE == spaceState) {
- if (revertDoubleSpaceWhileInBatchEdit(ic)) {
+ mHandler.cancelDoubleSpacesTimer();
+ if (mConnection.revertDoubleSpace()) {
// No need to reset mSpaceState, it has already be done (that's why we
// receive it as a parameter)
return;
}
} else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
- if (revertSwapPunctuation(ic)) {
+ if (mConnection.revertSwapPunctuation()) {
// Likewise
return;
}
@@ -1471,8 +1412,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mLastSelectionStart != mLastSelectionEnd) {
// If there is a selection, remove it.
final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart;
- ic.setSelection(mLastSelectionEnd, mLastSelectionEnd);
- ic.deleteSurroundingText(lengthToDelete, 0);
+ mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
+ mConnection.deleteSurroundingText(lengthToDelete, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(lengthToDelete);
}
@@ -1490,40 +1431,39 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are
// relying on this behavior so we continue to support it for older apps.
- sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_DEL, ic);
+ sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_DEL);
} else {
- ic.deleteSurroundingText(1, 0);
+ mConnection.deleteSurroundingText(1, 0);
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
if (mDeleteCount > DELETE_ACCELERATE_AT) {
- ic.deleteSurroundingText(1, 0);
+ mConnection.deleteSurroundingText(1, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
}
}
- if (isSuggestionsRequested()) {
- restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic);
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ restartSuggestionsOnWordBeforeCursorIfAtEndOfWord();
}
}
}
- // ic may be null
- private boolean maybeStripSpaceWhileInBatchEdit(final InputConnection ic, final int code,
+ private boolean maybeStripSpace(final int code,
final int spaceState, final boolean isFromSuggestionStrip) {
if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
- removeTrailingSpaceWhileInBatchEdit(ic);
+ mConnection.removeTrailingSpace();
return false;
} else if ((SPACE_STATE_WEAK == spaceState
|| SPACE_STATE_SWAP_PUNCTUATION == spaceState)
&& isFromSuggestionStrip) {
- if (mSettingsValues.isWeakSpaceSwapper(code)) {
+ if (mCurrentSettings.isWeakSpaceSwapper(code)) {
return true;
} else {
- if (mSettingsValues.isWeakSpaceStripper(code)) {
- removeTrailingSpaceWhileInBatchEdit(ic);
+ if (mCurrentSettings.isWeakSpaceStripper(code)) {
+ mConnection.removeTrailingSpace();
}
return false;
}
@@ -1534,20 +1474,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void handleCharacter(final int primaryCode, final int x,
final int y, final int spaceState) {
- final InputConnection ic = getCurrentInputConnection();
- if (null != ic) ic.beginBatchEdit();
- // TODO: if ic is null, does it make any sense to call this?
- handleCharacterWhileInBatchEdit(primaryCode, x, y, spaceState, ic);
- if (null != ic) ic.endBatchEdit();
- }
-
- // "ic" may be null without this crashing, but the behavior will be really strange
- private void handleCharacterWhileInBatchEdit(final int primaryCode,
- final int x, final int y, final int spaceState, final InputConnection ic) {
boolean isComposingWord = mWordComposer.isComposingWord();
if (SPACE_STATE_PHANTOM == spaceState &&
- !mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) {
+ !mCurrentSettings.isSymbolExcludedFromWordSeparators(primaryCode)) {
if (isComposingWord) {
// Sanity check
throw new RuntimeException("Should not be composing here");
@@ -1559,8 +1489,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// dozen milliseconds. Avoid calling it as much as possible, since we are on the UI
// thread here.
if (!isComposingWord && (isAlphabet(primaryCode)
- || mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode))
- && isSuggestionsRequested() && !isCursorTouchingWord()) {
+ || mCurrentSettings.isSymbolExcludedFromWordSeparators(primaryCode))
+ && mCurrentSettings.isSuggestionsRequested(mDisplayOrientation) &&
+ !mConnection.isCursorTouchingWord(mCurrentSettings)) {
// Reset entirely the composing state anyway, then start composing a new word unless
// the character is a single quote. The idea here is, single quote is not a
// separator and it should be treated as a normal character, except in the first
@@ -1576,23 +1507,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (isComposingWord) {
mWordComposer.add(
primaryCode, x, y, mKeyboardSwitcher.getKeyboardView().getKeyDetector());
- if (ic != null) {
- // If it's the first letter, make note of auto-caps state
- if (mWordComposer.size() == 1) {
- mWordComposer.setAutoCapitalized(
- getCurrentAutoCapsState() != Constants.TextUtils.CAP_MODE_OFF);
- }
- ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
+ // If it's the first letter, make note of auto-caps state
+ if (mWordComposer.size() == 1) {
+ mWordComposer.setAutoCapitalized(
+ getCurrentAutoCapsState() != Constants.TextUtils.CAP_MODE_OFF);
}
+ mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
mHandler.postUpdateSuggestions();
} else {
- final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode,
+ final boolean swapWeakSpace = maybeStripSpace(primaryCode,
spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x);
sendKeyCodePoint(primaryCode);
if (swapWeakSpace) {
- swapSwapperAndSpaceWhileInBatchEdit(ic);
+ swapSwapperAndSpace();
mSpaceState = SPACE_STATE_WEAK;
}
// Some characters are not word separators, yet they don't start a new
@@ -1619,37 +1548,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
boolean didAutoCorrect = false;
// Handle separator
- final InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.beginBatchEdit();
- }
if (mWordComposer.isComposingWord()) {
// In certain languages where single quote is a separator, it's better
// not to auto correct, but accept the typed word. For instance,
// in Italian dov' should not be expanded to dove' because the elision
// requires the last vowel to be removed.
- final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
- && !mInputAttributes.mInputTypeNoAutoCorrect;
- if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
- commitCurrentAutoCorrection(primaryCode, ic);
+ if (mCurrentSettings.mCorrectionEnabled && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
+ commitCurrentAutoCorrection(primaryCode);
didAutoCorrect = true;
} else {
- commitTyped(ic, primaryCode);
+ commitTyped(primaryCode);
}
}
- final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, spaceState,
+ final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x);
if (SPACE_STATE_PHANTOM == spaceState &&
- mSettingsValues.isPhantomSpacePromotingSymbol(primaryCode)) {
+ mCurrentSettings.isPhantomSpacePromotingSymbol(primaryCode)) {
sendKeyCodePoint(Keyboard.CODE_SPACE);
}
sendKeyCodePoint(primaryCode);
if (Keyboard.CODE_SPACE == primaryCode) {
- if (isSuggestionsRequested()) {
- if (maybeDoubleSpaceWhileInBatchEdit(ic)) {
+ if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ if (maybeDoubleSpace()) {
mSpaceState = SPACE_STATE_DOUBLE;
} else if (!isShowingPunctuationList()) {
mSpaceState = SPACE_STATE_WEAK;
@@ -1657,13 +1580,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
mHandler.startDoubleSpacesTimer();
- if (!isCursorTouchingWord()) {
+ if (!mConnection.isCursorTouchingWord(mCurrentSettings)) {
mHandler.cancelUpdateSuggestions();
mHandler.postUpdateBigramPredictions();
}
} else {
if (swapWeakSpace) {
- swapSwapperAndSpaceWhileInBatchEdit(ic);
+ swapSwapperAndSpace();
mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
} else if (SPACE_STATE_PHANTOM == spaceState) {
// If we are in phantom space state, and the user presses a separator, we want to
@@ -1682,9 +1605,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
Utils.Stats.onSeparator((char)primaryCode, x, y);
- if (ic != null) {
- ic.endBatchEdit();
- }
return didAutoCorrect;
}
@@ -1695,27 +1615,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void handleClose() {
- commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR);
+ commitTyped(LastComposedWord.NOT_A_SEPARATOR);
requestHideSelf(0);
LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null)
inputView.closing();
}
- public boolean isSuggestionsRequested() {
- return mInputAttributes.mIsSettingsSuggestionStripOn
- && (mCorrectionMode > 0 || isShowingSuggestionsStrip());
- }
-
public boolean isShowingPunctuationList() {
if (mSuggestionsView == null) return false;
- return mSettingsValues.mSuggestPuncList == mSuggestionsView.getSuggestions();
- }
-
- public boolean isShowingSuggestionsStrip() {
- return (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_VALUE)
- || (mSuggestionVisibility == SUGGESTION_VISIBILILTY_SHOW_ONLY_PORTRAIT_VALUE
- && mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT);
+ return mCurrentSettings.mSuggestPuncList == mSuggestionsView.getSuggestions();
}
public boolean isSuggestionsStripVisible() {
@@ -1723,11 +1632,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return false;
if (mSuggestionsView.isShowingAddToDictionaryHint())
return true;
- if (!isShowingSuggestionsStrip())
+ if (!mCurrentSettings.isSuggestionStripVisibleInOrientation(mDisplayOrientation))
return false;
- if (mInputAttributes.mApplicationSpecifiedCompletionOn)
+ if (mCurrentSettings.isApplicationSpecifiedCompletionsOn())
return true;
- return isSuggestionsRequested();
+ return mCurrentSettings.isSuggestionsRequested(mDisplayOrientation);
}
public void switchToKeyboardView() {
@@ -1765,20 +1674,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void setAutoCorrectionIndicator(final boolean newAutoCorrectionIndicator) {
// Put a blue underline to a word in TextView which will be auto-corrected.
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return;
if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator
&& mWordComposer.isComposingWord()) {
mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
final CharSequence textWithUnderline =
getTextWithUnderline(mWordComposer.getTypedWord());
- ic.setComposingText(textWithUnderline, 1);
+ mConnection.setComposingText(textWithUnderline, 1);
}
}
public void updateSuggestions() {
+ mHandler.cancelUpdateSuggestions();
+ mHandler.cancelUpdateBigramPredictions();
+
// Check if we have a suggestion engine attached.
- if ((mSuggest == null || !isSuggestionsRequested())) {
+ if ((mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation))) {
if (mWordComposer.isComposingWord()) {
Log.w(TAG, "Called updateSuggestions but suggestions were not requested!");
mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
@@ -1786,27 +1696,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
- mHandler.cancelUpdateSuggestions();
- mHandler.cancelUpdateBigramPredictions();
-
if (!mWordComposer.isComposingWord()) {
+ // This is dead code: we can't come here with an empty word composer.
setPunctuationSuggestions();
return;
}
// TODO: May need a better way of retrieving previous word
- final InputConnection ic = getCurrentInputConnection();
- final CharSequence prevWord;
- if (null == ic) {
- prevWord = null;
- } else {
- prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators);
- }
-
+ final CharSequence prevWord = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators);
final CharSequence typedWord = mWordComposer.getTypedWord();
// getSuggestedWords handles gracefully a null value of prevWord
final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
- prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode);
+ prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
+ mCurrentSettings.mCorrectionEnabled, false);
// Basically, we update the suggestion strip only when suggestion count > 1. However,
// there is an exception: We update the suggestion strip whenever typed word's length
@@ -1815,12 +1717,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// need to clear the previous state when the user starts typing a word (i.e. typed word's
// length == 1).
if (suggestedWords.size() > 1 || typedWord.length() == 1
- || !suggestedWords.mAllowsToBeAutoCorrected
+ || !suggestedWords.mTypedWordValid
|| mSuggestionsView.isShowingAddToDictionaryHint()) {
showSuggestions(suggestedWords, typedWord);
} else {
SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions();
- if (previousSuggestions == mSettingsValues.mSuggestPuncList) {
+ if (previousSuggestions == mCurrentSettings.mSuggestPuncList) {
previousSuggestions = SuggestedWords.EMPTY;
}
final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
@@ -1830,7 +1732,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
new SuggestedWords(typedWordAndPreviousSuggestions,
false /* typedWordValid */,
false /* hasAutoCorrectionCandidate */,
- false /* allowsToBeAutoCorrected */,
false /* isPunctuationSuggestions */,
true /* isObsoleteSuggestions */,
false /* isPrediction */);
@@ -1856,8 +1757,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
setSuggestionStripShown(isSuggestionsStripVisible());
}
- private void commitCurrentAutoCorrection(final int separatorCodePoint,
- final InputConnection ic) {
+ private void commitCurrentAutoCorrection(final int separatorCodePoint) {
// Complete any pending suggestions query first
if (mHandler.hasPendingUpdateSuggestions()) {
mHandler.cancelUpdateSuggestions();
@@ -1878,10 +1778,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mExpectingUpdateSelection = true;
commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD,
separatorCodePoint);
- if (!typedWord.equals(autoCorrection) && null != ic) {
+ if (!typedWord.equals(autoCorrection)) {
// This will make the correction flash for a short while as a visual clue
// to the user that auto-correction happened.
- ic.commitCorrection(new CorrectionInfo(mLastSelectionEnd - typedWord.length(),
+ mConnection.commitCorrection(
+ new CorrectionInfo(mLastSelectionEnd - typedWord.length(),
typedWord, autoCorrection));
}
}
@@ -1889,15 +1790,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void pickSuggestionManually(final int index, final CharSequence suggestion,
- int x, int y) {
- final InputConnection ic = getCurrentInputConnection();
- if (null != ic) ic.beginBatchEdit();
- pickSuggestionManuallyWhileInBatchEdit(index, suggestion, x, y, ic);
- if (null != ic) ic.endBatchEdit();
- }
-
- public void pickSuggestionManuallyWhileInBatchEdit(final int index,
- final CharSequence suggestion, final int x, final int y, final InputConnection ic) {
+ final int x, final int y) {
final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
// If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
if (suggestion.length() == 1 && isShowingPunctuationList()) {
@@ -1917,13 +1810,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) {
int firstChar = Character.codePointAt(suggestion, 0);
- if ((!mSettingsValues.isWeakSpaceStripper(firstChar))
- && (!mSettingsValues.isWeakSpaceSwapper(firstChar))) {
+ if ((!mCurrentSettings.isWeakSpaceStripper(firstChar))
+ && (!mCurrentSettings.isWeakSpaceSwapper(firstChar))) {
sendKeyCodePoint(Keyboard.CODE_SPACE);
}
}
- if (mInputAttributes.mApplicationSpecifiedCompletionOn
+ if (mCurrentSettings.isApplicationSpecifiedCompletionsOn()
&& mApplicationSpecifiedCompletions != null
&& index >= 0 && index < mApplicationSpecifiedCompletions.length) {
if (mSuggestionsView != null) {
@@ -1931,13 +1824,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
mKeyboardSwitcher.updateShiftState();
resetComposingState(true /* alsoResetLastComposedWord */);
- if (ic != null) {
- final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
- ic.commitCompletion(completionInfo);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_pickApplicationSpecifiedCompletion(index,
- completionInfo.getText(), x, y);
- }
+ final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
+ mConnection.beginBatchEdit(getCurrentInputConnection());
+ mConnection.commitCompletion(completionInfo);
+ mConnection.endBatchEdit();
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_pickApplicationSpecifiedCompletion(index,
+ completionInfo.getText(), x, y);
}
return;
}
@@ -1966,8 +1859,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// - There is a dictionary and the word is not in it
// Please note that if mSuggest is null, it means that everything is off: suggestion
// and correction, so we shouldn't try to show the hint
- // We used to look at mCorrectionMode here, but showing the hint should have nothing
- // to do with the autocorrection setting.
final boolean showingAddToDictionaryHint = index == 0 && mSuggest != null
// If there is no dictionary the hint should be shown.
&& (!mSuggest.hasMainDictionary()
@@ -1987,7 +1878,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
if (mIsUserDictionaryAvailable) {
mSuggestionsView.showAddToDictionaryHint(
- suggestion, mSettingsValues.mHintToSaveText);
+ suggestion, mCurrentSettings.mHintToSaveText);
} else {
mHandler.postUpdateSuggestions();
}
@@ -1999,22 +1890,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
*/
private void commitChosenWord(final CharSequence chosenWord, final int commitType,
final int separatorCode) {
- final InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- if (mSettingsValues.mEnableSuggestionSpanInsertion) {
- final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
- ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
- this, chosenWord, suggestedWords, mIsMainDictionaryAvailable),
- 1);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_commitText(chosenWord);
- }
- } else {
- ic.commitText(chosenWord, 1);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_commitText(chosenWord);
- }
- }
+ final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
+ mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
+ this, chosenWord, suggestedWords, mIsMainDictionaryAvailable), 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_commitText(chosenWord);
}
// Add the word to the user history dictionary
final CharSequence prevWord = addToUserHistoryDictionary(chosenWord);
@@ -2027,20 +1907,29 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public void updateBigramPredictions() {
- if (mSuggest == null || !isSuggestionsRequested())
+ mHandler.cancelUpdateSuggestions();
+ mHandler.cancelUpdateBigramPredictions();
+
+ if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
+ if (mWordComposer.isComposingWord()) {
+ Log.w(TAG, "Called updateBigramPredictions but suggestions were not requested!");
+ mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
+ }
return;
+ }
- if (!mSettingsValues.mBigramPredictionEnabled) {
+ if (!mCurrentSettings.mBigramPredictionEnabled) {
setPunctuationSuggestions();
return;
}
final SuggestedWords suggestedWords;
- if (mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) {
- final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(),
- mSettingsValues.mWordSeparators);
+ if (mCurrentSettings.mCorrectionEnabled) {
+ final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators);
if (!TextUtils.isEmpty(prevWord)) {
- suggestedWords = mSuggest.getBigramPredictions(prevWord);
+ suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
+ prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
+ mCurrentSettings.mCorrectionEnabled, true);
} else {
suggestedWords = null;
}
@@ -2058,10 +1947,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public void setPunctuationSuggestions() {
- if (mSettingsValues.mBigramPredictionEnabled) {
+ if (mCurrentSettings.mBigramPredictionEnabled) {
clearSuggestions();
} else {
- setSuggestions(mSettingsValues.mSuggestPuncList, false);
+ setSuggestions(mCurrentSettings.mSuggestPuncList, false);
}
setAutoCorrectionIndicator(false);
setSuggestionStripShown(isSuggestionsStripVisible());
@@ -2070,22 +1959,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private CharSequence addToUserHistoryDictionary(final CharSequence suggestion) {
if (TextUtils.isEmpty(suggestion)) return null;
- // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be
- // adding words in situations where the user or application really didn't
- // want corrections enabled or learned.
- if (!(mCorrectionMode == Suggest.CORRECTION_FULL
- || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) {
- return null;
- }
+ // If correction is not enabled, we don't add words to the user history dictionary.
+ // That's to avoid unintended additions in some sensitive fields, or fields that
+ // expect to receive non-words.
+ if (!mCurrentSettings.mCorrectionEnabled) return null;
- if (mUserHistoryDictionary != null) {
- final InputConnection ic = getCurrentInputConnection();
- final CharSequence prevWord;
- if (null != ic) {
- prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators);
- } else {
- prevWord = null;
- }
+ final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary;
+ if (userHistoryDictionary != null) {
+ final CharSequence prevWord
+ = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators);
final String secondWord;
if (mWordComposer.isAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
secondWord = suggestion.toString().toLowerCase(
@@ -2098,95 +1980,36 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final int maxFreq = AutoCorrection.getMaxFrequency(
mSuggest.getUnigramDictionaries(), suggestion);
if (maxFreq == 0) return null;
- mUserHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(),
+ userHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(),
secondWord, maxFreq > 0);
return prevWord;
}
return null;
}
- public boolean isCursorTouchingWord() {
- final InputConnection ic = getCurrentInputConnection();
- if (ic == null) return false;
- CharSequence before = ic.getTextBeforeCursor(1, 0);
- CharSequence after = ic.getTextAfterCursor(1, 0);
- if (!TextUtils.isEmpty(before) && !mSettingsValues.isWordSeparator(before.charAt(0))
- && !mSettingsValues.isSymbolExcludedFromWordSeparators(before.charAt(0))) {
- return true;
- }
- if (!TextUtils.isEmpty(after) && !mSettingsValues.isWordSeparator(after.charAt(0))
- && !mSettingsValues.isSymbolExcludedFromWordSeparators(after.charAt(0))) {
- return true;
- }
- return false;
- }
-
- // "ic" must not be null
- private static boolean sameAsTextBeforeCursor(final InputConnection ic,
- final CharSequence text) {
- final CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0);
- return TextUtils.equals(text, beforeText);
- }
-
- // "ic" must not be null
/**
* Check if the cursor is actually at the end of a word. If so, restart suggestions on this
* word, else do nothing.
*/
- private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(
- final InputConnection ic) {
- // Bail out if the cursor is not at the end of a word (cursor must be preceded by
- // non-whitespace, non-separator, non-start-of-text)
- // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
- final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0);
- if (TextUtils.isEmpty(textBeforeCursor)
- || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return;
-
- // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
- // separator or end of line/text)
- // Example: "test|"<EOL> "te|st" get rejected here
- final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0);
- if (!TextUtils.isEmpty(textAfterCursor)
- && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return;
-
- // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe)
- // Example: " -|" gets rejected here but "e-|" and "e|" are okay
- CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators);
- // We don't suggest on leading single quotes, so we have to remove them from the word if
- // it starts with single quotes.
- while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) {
- word = word.subSequence(1, word.length());
- }
- if (TextUtils.isEmpty(word)) return;
- final char firstChar = word.charAt(0); // we just tested that word is not empty
- if (word.length() == 1 && !Character.isLetter(firstChar)) return;
-
- // We only suggest on words that start with a letter or a symbol that is excluded from
- // word separators (see #handleCharacterWhileInBatchEdit).
- if (!(isAlphabet(firstChar)
- || mSettingsValues.isSymbolExcludedFromWordSeparators(firstChar))) {
- return;
+ private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() {
+ final CharSequence word = mConnection.getWordBeforeCursorIfAtEndOfWord(mCurrentSettings);
+ if (null != word) {
+ restartSuggestionsOnWordBeforeCursor(word);
}
-
- // Okay, we are at the end of a word. Restart suggestions.
- restartSuggestionsOnWordBeforeCursor(ic, word);
}
- // "ic" must not be null
- private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic,
- final CharSequence word) {
+ private void restartSuggestionsOnWordBeforeCursor(final CharSequence word) {
mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard());
final int length = word.length();
- ic.deleteSurroundingText(length, 0);
+ mConnection.deleteSurroundingText(length, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(length);
}
- ic.setComposingText(word, 1);
+ mConnection.setComposingText(word, 1);
mHandler.postUpdateSuggestions();
}
- // "ic" must not be null
- private void revertCommit(final InputConnection ic) {
+ private void revertCommit() {
final CharSequence previousWord = mLastComposedWord.mPrevWord;
final String originallyTypedWord = mLastComposedWord.mTypedWord;
final CharSequence committedWord = mLastComposedWord.mCommittedWord;
@@ -2200,7 +2023,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
throw new RuntimeException("revertCommit, but we are composing a word");
}
final String wordBeforeCursor =
- ic.getTextBeforeCursor(deleteLength, 0)
+ mConnection.getTextBeforeCursor(deleteLength, 0)
.subSequence(0, cancelLength).toString();
if (!TextUtils.equals(committedWord, wordBeforeCursor)) {
throw new RuntimeException("revertCommit check failed: we thought we were "
@@ -2208,7 +2031,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ "\", but before the cursor we found \"" + wordBeforeCursor + "\"");
}
}
- ic.deleteSurroundingText(deleteLength, 0);
+ mConnection.deleteSurroundingText(deleteLength, 0);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(deleteLength);
}
@@ -2220,9 +2043,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This is the case when we cancel a manual pick.
// We should restart suggestion on the word right away.
mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord);
- ic.setComposingText(originallyTypedWord, 1);
+ mConnection.setComposingText(originallyTypedWord, 1);
} else {
- ic.commitText(originallyTypedWord, 1);
+ mConnection.commitText(originallyTypedWord, 1);
// Re-insert the separator
sendKeyCodePoint(mLastComposedWord.mSeparatorCode);
Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE,
@@ -2238,61 +2061,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.postUpdateSuggestions();
}
- // "ic" must not be null
- private boolean revertDoubleSpaceWhileInBatchEdit(final InputConnection ic) {
- mHandler.cancelDoubleSpacesTimer();
- // Here we test whether we indeed have a period and a space before us. This should not
- // be needed, but it's there just in case something went wrong.
- final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
- if (!". ".equals(textBeforeCursor)) {
- // Theoretically we should not be coming here if there isn't ". " before the
- // cursor, but the application may be changing the text while we are typing, so
- // anything goes. We should not crash.
- Log.d(TAG, "Tried to revert double-space combo but we didn't find "
- + "\". \" just before the cursor.");
- return false;
- }
- ic.deleteSurroundingText(2, 0);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_deleteSurroundingText(2);
- }
- ic.commitText(" ", 1);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_revertDoubleSpaceWhileInBatchEdit();
- }
- return true;
- }
-
- private static boolean revertSwapPunctuation(final InputConnection ic) {
- // Here we test whether we indeed have a space and something else before us. This should not
- // be needed, but it's there just in case something went wrong.
- final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0);
- // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
- // enter surrogate pairs this code will have been removed.
- if (TextUtils.isEmpty(textBeforeCursor)
- || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) {
- // We may only come here if the application is changing the text while we are typing.
- // This is quite a broken case, but not logically impossible, so we shouldn't crash,
- // but some debugging log may be in order.
- Log.d(TAG, "Tried to revert a swap of punctuation but we didn't "
- + "find a space just before the cursor.");
- return false;
- }
- ic.beginBatchEdit();
- ic.deleteSurroundingText(2, 0);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_deleteSurroundingText(2);
- }
- ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
- if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_revertSwapPunctuation();
- }
- ic.endBatchEdit();
- return true;
- }
-
public boolean isWordSeparator(int code) {
- return mSettingsValues.isWordSeparator(code);
+ return mCurrentSettings.isWordSeparator(code);
}
public boolean preferCapitalization() {
@@ -2306,15 +2076,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// onConfigurationChanged before SoftInputWindow is shown.
if (mKeyboardSwitcher.getKeyboardView() != null) {
// Reload keyboard because the current language has been changed.
- mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues);
+ mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mCurrentSettings);
}
initSuggest();
- updateCorrectionMode();
loadSettings();
// Since we just changed languages, we should re-evaluate suggestions with whatever word
// we are currently composing. If we are not composing anything, we may want to display
// predictions or punctuation signs (which is done by updateBigramPredictions anyway).
- if (isCursorTouchingWord()) {
+ if (mConnection.isCursorTouchingWord(mCurrentSettings)) {
mHandler.postUpdateSuggestions();
} else {
mHandler.postUpdateBigramPredictions();
@@ -2352,12 +2121,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This is a stopgap solution to avoid leaving a high surrogate alone in a text view.
// In the future, we need to deprecate deteleSurroundingText() and have a surrogate
// pair-friendly way of deleting characters in InputConnection.
- final InputConnection ic = getCurrentInputConnection();
- if (null != ic) {
- final CharSequence lastChar = ic.getTextBeforeCursor(1, 0);
- if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) {
- ic.deleteSurroundingText(1, 0);
- }
+ final CharSequence lastChar = mConnection.getTextBeforeCursor(1, 0);
+ if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) {
+ mConnection.deleteSurroundingText(1, 0);
}
}
}
@@ -2375,25 +2141,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
};
- private void updateCorrectionMode() {
- // TODO: cleanup messy flags
- final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled
- && !mInputAttributes.mInputTypeNoAutoCorrect;
- mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE;
- mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect)
- ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode;
- }
-
- private void updateSuggestionVisibility(final Resources res) {
- final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting;
- for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) {
- if (suggestionVisiblityStr.equals(res.getString(visibility))) {
- mSuggestionVisibility = visibility;
- break;
- }
- }
- }
-
private void launchSettings() {
launchSettingsClass(SettingsActivity.class);
}
@@ -2440,10 +2187,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setItems(items, listener)
.setTitle(title);
- showOptionDialogInternal(builder.create());
+ showOptionDialog(builder.create());
}
- private void showOptionDialogInternal(AlertDialog dialog) {
+ /* package */ void showOptionDialog(AlertDialog dialog) {
final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken();
if (windowToken == null) return;
@@ -2470,13 +2217,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1;
p.println(" Keyboard mode = " + keyboardMode);
- p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn);
- p.println(" mCorrectionMode=" + mCorrectionMode);
+ p.println(" mIsSuggestionsSuggestionsRequested = "
+ + mCurrentSettings.isSuggestionsRequested(mDisplayOrientation));
+ p.println(" mCorrectionEnabled=" + mCurrentSettings.mCorrectionEnabled);
p.println(" isComposingWord=" + mWordComposer.isComposingWord());
- p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled);
- p.println(" mSoundOn=" + mSettingsValues.mSoundOn);
- p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn);
- p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn);
- p.println(" mInputAttributes=" + mInputAttributes.toString());
+ p.println(" mSoundOn=" + mCurrentSettings.mSoundOn);
+ p.println(" mVibrateOn=" + mCurrentSettings.mVibrateOn);
+ p.println(" mKeyPreviewPopupOn=" + mCurrentSettings.mKeyPreviewPopupOn);
+ p.println(" inputAttributes=" + mCurrentSettings.getInputAttributesDebugString());
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index dc0868e7c..e843848bc 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -71,7 +71,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void onStartSuggestion(CharSequence previousWords) {
}
- public static void onAddSuggestedWord(String word, int typeId, int dataType) {
+ public static void onAddSuggestedWord(String word, String sourceDictionaryId) {
}
public static void onSetKeyboard(Keyboard kb) {
diff --git a/java/src/com/android/inputmethod/latin/NativeUtils.java b/java/src/com/android/inputmethod/latin/NativeUtils.java
new file mode 100644
index 000000000..9cc2bc02e
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/NativeUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+public class NativeUtils {
+ static {
+ JniUtils.loadNativeLibrary();
+ }
+
+ private NativeUtils() {
+ // This utility class is not publicly instantiable.
+ }
+
+ /**
+ * This method just calls up libm's powf() directly.
+ */
+ public static native float powf(float x, float y);
+}
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index 66d6d58b1..79e1d376c 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -16,37 +16,47 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
import android.inputmethodservice.InputMethodService;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.os.SystemClock;
-import android.preference.PreferenceManager;
import android.text.TextUtils;
+import android.util.JsonWriter;
import android.util.Log;
import android.view.MotionEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.widget.Toast;
import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.internal.KeyboardState;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.RichInputConnection.Range;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.define.ProductionFlag;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.charset.Charset;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.UUID;
/**
* Logs the use of the LatinIME keyboard.
@@ -58,700 +68,1024 @@ import java.util.Map;
*/
public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = ResearchLogger.class.getSimpleName();
- private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
private static final boolean DEBUG = false;
+ private static final boolean OUTPUT_ENTIRE_BUFFER = false; // true may disclose private info
+ /* package */ static boolean sIsLogging = false;
+ private static final int OUTPUT_FORMAT_VERSION = 1;
+ private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+ private static final String FILENAME_PREFIX = "researchLog";
+ private static final String FILENAME_SUFFIX = ".txt";
+ private static final JsonWriter NULL_JSON_WRITER = new JsonWriter(
+ new OutputStreamWriter(new NullOutputStream()));
+ private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
+ new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
+
+ // 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 ResearchLogger sInstance = new ResearchLogger();
+ private HandlerThread mHandlerThread;
+ /* package */ Handler mLoggingHandler;
+ // to write to a different filename, e.g., for testing, set mFile before calling start()
+ private File mFilesDir;
+ /* package */ File mFile;
+ private JsonWriter mJsonWriter = NULL_JSON_WRITER; // should never be null
+
+ private int mLoggingState;
+ private static final int LOGGING_STATE_OFF = 0;
+ private static final int LOGGING_STATE_ON = 1;
+ private static final int LOGGING_STATE_STOPPING = 2;
+ private boolean mIsPasswordView = false;
+
+ // digits entered by the user are replaced with this codepoint.
+ /* package for test */ static final int DIGIT_REPLACEMENT_CODEPOINT =
+ Character.codePointAt("\uE000", 0); // U+E000 is in the "private-use area"
+ // U+E001 is in the "private-use area"
+ /* package for test */ static final String WORD_REPLACEMENT_STRING = "\uE001";
+ // set when LatinIME should ignore an onUpdateSelection() callback that
+ // arises from operations in this class
+ private static boolean sLatinIMEExpectingUpdateSelection = false;
+
+ // used to check whether words are not unique
+ private Suggest mSuggest;
+ private Dictionary mDictionary;
+
+ private static class NullOutputStream extends OutputStream {
+ /** {@inheritDoc} */
+ @Override
+ public void write(byte[] buffer, int offset, int count) {
+ // nop
+ }
- private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager());
- public static boolean sIsLogging = false;
- /* package */ final Handler mLoggingHandler;
- private InputMethodService mIms;
-
- /**
- * Isolates management of files. This variable should never be null, but can be changed
- * to support testing.
- */
- /* package */ LogFileManager mLogFileManager;
-
- /**
- * Manages the file(s) that stores the logs.
- *
- * Handles creation, deletion, and provides Readers, Writers, and InputStreams to access
- * the logs.
- */
- /* package */ static class LogFileManager {
- public static final String RESEARCH_LOG_FILENAME_KEY = "RESEARCH_LOG_FILENAME";
+ /** {@inheritDoc} */
+ @Override
+ public void write(byte[] buffer) {
+ // nop
+ }
- private static final String DEFAULT_FILENAME = "researchLog.txt";
- private static final long LOGFILE_PURGE_INTERVAL = 1000 * 60 * 60 * 24;
+ @Override
+ public void write(int oneByte) {
+ }
+ }
- protected InputMethodService mIms;
- protected File mFile;
- protected PrintWriter mPrintWriter;
+ private ResearchLogger() {
+ mLoggingState = LOGGING_STATE_OFF;
+ }
- /* package */ LogFileManager() {
- }
+ public static ResearchLogger getInstance() {
+ return sInstance;
+ }
- public void init(final InputMethodService ims) {
- mIms = ims;
+ public void init(final InputMethodService ims, final SharedPreferences prefs) {
+ assert ims != null;
+ if (ims == null) {
+ Log.w(TAG, "IMS is null; logging is off");
+ } else {
+ mFilesDir = ims.getFilesDir();
+ if (mFilesDir == null || !mFilesDir.exists()) {
+ Log.w(TAG, "IME storage directory does not exist.");
+ }
}
-
- public synchronized void createLogFile() throws IOException {
- createLogFile(DEFAULT_FILENAME);
+ if (prefs != null) {
+ sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
+ prefs.registerOnSharedPreferenceChangeListener(this);
}
+ }
- public synchronized void createLogFile(final SharedPreferences prefs)
- throws IOException {
- final String filename =
- prefs.getString(RESEARCH_LOG_FILENAME_KEY, DEFAULT_FILENAME);
- createLogFile(filename);
+ public synchronized void start() {
+ Log.d(TAG, "start called");
+ if (!sIsLogging) {
+ // Log.w(TAG, "not in usability mode; not logging");
+ return;
}
-
- public synchronized void createLogFile(final String filename)
- throws IOException {
- if (mIms == null) {
- final String msg = "InputMethodService is not configured. Logging is off.";
- Log.w(TAG, msg);
- throw new IOException(msg);
+ if (mFilesDir == null || !mFilesDir.exists()) {
+ Log.w(TAG, "IME storage directory does not exist. Cannot start logging.");
+ } else {
+ if (mHandlerThread == null || !mHandlerThread.isAlive()) {
+ mHandlerThread = new HandlerThread("ResearchLogger logging task",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ mHandlerThread.start();
+ mLoggingHandler = null;
+ mLoggingState = LOGGING_STATE_OFF;
}
- final File filesDir = mIms.getFilesDir();
- if (filesDir == null || !filesDir.exists()) {
- final String msg = "Storage directory does not exist. Logging is off.";
- Log.w(TAG, msg);
- throw new IOException(msg);
+ if (mLoggingHandler == null) {
+ mLoggingHandler = new Handler(mHandlerThread.getLooper());
+ mLoggingState = LOGGING_STATE_OFF;
}
- close();
- final File file = new File(filesDir, filename);
- mFile = file;
- boolean append = true;
- if (file.exists() && file.lastModified() + LOGFILE_PURGE_INTERVAL <
- System.currentTimeMillis()) {
- append = false;
+ if (mFile == null) {
+ final String timestampString = TIMESTAMP_DATEFORMAT.format(new Date());
+ mFile = new File(mFilesDir, FILENAME_PREFIX + timestampString + FILENAME_SUFFIX);
}
- mPrintWriter = new PrintWriter(new BufferedWriter(new FileWriter(file, append)), true);
- }
-
- public synchronized boolean append(final String s) {
- PrintWriter printWriter = mPrintWriter;
- if (printWriter == null || !mFile.exists()) {
- if (DEBUG) {
- Log.w(TAG, "PrintWriter is null... attempting to create default log file");
- }
+ if (mLoggingState == LOGGING_STATE_OFF) {
try {
- createLogFile();
- printWriter = mPrintWriter;
+ mJsonWriter = new JsonWriter(new BufferedWriter(new FileWriter(mFile)));
+ mJsonWriter.setLenient(true);
+ mJsonWriter.beginArray();
+ mLoggingState = LOGGING_STATE_ON;
} catch (IOException e) {
- Log.w(TAG, "Failed to create log file. Not logging.");
- return false;
+ Log.w(TAG, "cannot start JsonWriter");
+ mJsonWriter = NULL_JSON_WRITER;
+ e.printStackTrace();
}
}
- printWriter.print(s);
- printWriter.flush();
- return !printWriter.checkError();
}
+ }
- public synchronized void reset() {
- if (mPrintWriter != null) {
- mPrintWriter.close();
- mPrintWriter = null;
- if (DEBUG) {
- Log.d(TAG, "logfile closed");
- }
- }
- if (mFile != null) {
- mFile.delete();
- if (DEBUG) {
- Log.d(TAG, "logfile deleted");
+ public synchronized void stop() {
+ Log.d(TAG, "stop called");
+ if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
+ mLoggingState = LOGGING_STATE_STOPPING;
+ flushEventQueue(true);
+ // put this in the Handler queue so pending writes are processed first.
+ mLoggingHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Log.d(TAG, "closing jsonwriter");
+ mJsonWriter.endArray();
+ mJsonWriter.flush();
+ mJsonWriter.close();
+ } catch (IllegalStateException e1) {
+ // assume that this is just the json not being terminated properly.
+ // ignore
+ e1.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mJsonWriter = NULL_JSON_WRITER;
+ mFile = null;
+ mLoggingState = LOGGING_STATE_OFF;
+ if (DEBUG) {
+ Log.d(TAG, "logfile closed");
+ }
+ Log.d(TAG, "finished stop(), notifying");
+ synchronized (ResearchLogger.this) {
+ ResearchLogger.this.notify();
+ }
+ }
}
- mFile = null;
+ });
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
}
}
+ }
- public synchronized void close() {
- if (mPrintWriter != null) {
- mPrintWriter.close();
- mPrintWriter = null;
+ public synchronized boolean abort() {
+ Log.d(TAG, "abort called");
+ boolean isLogFileDeleted = false;
+ if (mLoggingHandler != null && mLoggingState == LOGGING_STATE_ON) {
+ mLoggingState = LOGGING_STATE_STOPPING;
+ try {
+ Log.d(TAG, "closing jsonwriter");
+ mJsonWriter.endArray();
+ mJsonWriter.close();
+ } catch (IllegalStateException e1) {
+ // assume that this is just the json not being terminated properly.
+ // ignore
+ e1.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mJsonWriter = NULL_JSON_WRITER;
+ // delete file
+ final boolean isDeleted = mFile.delete();
+ if (isDeleted) {
+ isLogFileDeleted = true;
+ }
mFile = null;
+ mLoggingState = LOGGING_STATE_OFF;
if (DEBUG) {
Log.d(TAG, "logfile closed");
}
}
}
+ return isLogFileDeleted;
+ }
+
+ /* package */ synchronized void flush() {
+ try {
+ mJsonWriter.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
- /* package */ synchronized void flush() {
- if (mPrintWriter != null) {
- mPrintWriter.flush();
- }
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ if (key == null || prefs == null) {
+ return;
+ }
+ sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
+ if (sIsLogging == false) {
+ abort();
}
+ }
- /* package */ synchronized String getContents() {
- final File file = mFile;
- if (file == null) {
- return "";
- }
- if (mPrintWriter != null) {
- mPrintWriter.flush();
- }
- FileInputStream stream = null;
- FileChannel fileChannel = null;
- String s = "";
- try {
- stream = new FileInputStream(file);
- fileChannel = stream.getChannel();
- final ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length());
- fileChannel.read(byteBuffer);
- byteBuffer.rewind();
- CharBuffer charBuffer = Charset.defaultCharset().decode(byteBuffer);
- s = charBuffer.toString();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (fileChannel != null) {
- fileChannel.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (stream != null) {
- stream.close();
+ /* package */ void presentResearchDialog(final LatinIME latinIME) {
+ final CharSequence title = latinIME.getString(R.string.english_ime_research_log);
+ final CharSequence[] items = new CharSequence[] {
+ latinIME.getString(R.string.note_timestamp_for_researchlog),
+ latinIME.getString(R.string.do_not_log_this_session),
+ };
+ final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface di, int position) {
+ di.dismiss();
+ switch (position) {
+ case 0:
+ ResearchLogger.getInstance().userTimestamp();
+ Toast.makeText(latinIME, R.string.notify_recorded_timestamp,
+ Toast.LENGTH_LONG).show();
+ break;
+ case 1:
+ Toast toast = Toast.makeText(latinIME,
+ R.string.notify_session_log_deleting, Toast.LENGTH_LONG);
+ toast.show();
+ final ResearchLogger logger = ResearchLogger.getInstance();
+ boolean isLogDeleted = logger.abort();
+ toast.cancel();
+ if (isLogDeleted) {
+ Toast.makeText(latinIME, R.string.notify_session_log_deleted,
+ Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(latinIME,
+ R.string.notify_session_log_not_deleted, Toast.LENGTH_LONG)
+ .show();
}
- } catch (IOException e) {
- e.printStackTrace();
- }
+ break;
}
}
- return s;
- }
+ };
+ final AlertDialog.Builder builder = new AlertDialog.Builder(latinIME)
+ .setItems(items, listener)
+ .setTitle(title);
+ latinIME.showOptionDialog(builder.create());
}
- private ResearchLogger(final LogFileManager logFileManager) {
- final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task",
- Process.THREAD_PRIORITY_BACKGROUND);
- handlerThread.start();
- mLoggingHandler = new Handler(handlerThread.getLooper());
- mLogFileManager = logFileManager;
+ public void initSuggest(Suggest suggest) {
+ mSuggest = suggest;
}
- public static ResearchLogger getInstance() {
- return sInstance;
+ private void setIsPasswordView(boolean isPasswordView) {
+ mIsPasswordView = isPasswordView;
}
- public static void init(final InputMethodService ims, final SharedPreferences prefs) {
- sInstance.initInternal(ims, prefs);
+ private boolean isAllowedToLog() {
+ return mLoggingState == LOGGING_STATE_ON && !mIsPasswordView;
}
- /* package */ void initInternal(final InputMethodService ims, final SharedPreferences prefs) {
- mIms = ims;
- final LogFileManager logFileManager = mLogFileManager;
- if (logFileManager != null) {
- logFileManager.init(ims);
- try {
- logFileManager.createLogFile(prefs);
- } catch (IOException e) {
- e.printStackTrace();
+ private static final String CURRENT_TIME_KEY = "_ct";
+ private static final String UPTIME_KEY = "_ut";
+ private static final String EVENT_TYPE_KEY = "_ty";
+ private static final Object[] EVENTKEYS_NULLVALUES = {};
+
+ private LogUnit mCurrentLogUnit = new LogUnit();
+
+ /**
+ * Buffer a research log event, flagging it as privacy-sensitive.
+ *
+ * This event contains potentially private information. If the word that this event is a part
+ * of is determined to be privacy-sensitive, then this event should not be included in the
+ * output log. The system waits to output until the containing word is known.
+ *
+ * @param keys an array containing a descriptive name for the event, followed by the keys
+ * @param values an array of values, either a String or Number. length should be one
+ * less than the keys array
+ */
+ private synchronized void enqueuePotentiallyPrivateEvent(final String[] keys,
+ final Object[] values) {
+ assert values.length + 1 == keys.length;
+ mCurrentLogUnit.addLogAtom(keys, values, true);
+ }
+
+ /**
+ * Buffer a research log event, flaggint it as not privacy-sensitive.
+ *
+ * This event contains no potentially private information. Even if the word that this event
+ * is privacy-sensitive, this event can still safely be sent to the output log. The system
+ * waits until the containing word is known so that this event can be written in the proper
+ * temporal order with other events that may be privacy sensitive.
+ *
+ * @param keys an array containing a descriptive name for the event, followed by the keys
+ * @param values an array of values, either a String or Number. length should be one
+ * less than the keys array
+ */
+ private synchronized void enqueueEvent(final String[] keys, final Object[] values) {
+ assert values.length + 1 == keys.length;
+ mCurrentLogUnit.addLogAtom(keys, values, false);
+ }
+
+ // Used to track how often words are logged. Too-frequent logging can leak
+ // semantics, disclosing private data.
+ /* package for test */ static class LoggingFrequencyState {
+ private static final int DEFAULT_WORD_LOG_FREQUENCY = 10;
+ private int mWordsRemainingToSkip;
+ private final int mFrequency;
+
+ /**
+ * Tracks how often words may be uploaded.
+ *
+ * @param frequency 1=Every word, 2=Every other word, etc.
+ */
+ public LoggingFrequencyState(int frequency) {
+ mFrequency = frequency;
+ mWordsRemainingToSkip = mFrequency;
+ }
+
+ public void onWordLogged() {
+ mWordsRemainingToSkip = mFrequency;
+ }
+
+ public void onWordNotLogged() {
+ if (mWordsRemainingToSkip > 1) {
+ mWordsRemainingToSkip--;
}
}
- if (prefs != null) {
- sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
- prefs.registerOnSharedPreferenceChangeListener(this);
+
+ public boolean isSafeToLog() {
+ return mWordsRemainingToSkip <= 1;
+ }
+ }
+
+ /* package for test */ LoggingFrequencyState mLoggingFrequencyState =
+ new LoggingFrequencyState(LoggingFrequencyState.DEFAULT_WORD_LOG_FREQUENCY);
+
+ /* package for test */ boolean isPrivacyThreat(String word) {
+ // Current checks:
+ // - Word not in dictionary
+ // - Word contains numbers
+ // - Privacy-safe word not logged recently
+ if (TextUtils.isEmpty(word)) {
+ return false;
+ }
+ if (!mLoggingFrequencyState.isSafeToLog()) {
+ return true;
+ }
+ final int length = word.length();
+ boolean hasLetter = false;
+ for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
+ final int codePoint = Character.codePointAt(word, i);
+ if (Character.isDigit(codePoint)) {
+ return true;
+ }
+ if (Character.isLetter(codePoint)) {
+ hasLetter = true;
+ break; // Word may contain digits, but will only be allowed if in the dictionary.
+ }
+ }
+ if (hasLetter) {
+ if (mDictionary == null && mSuggest != null && mSuggest.hasMainDictionary()) {
+ mDictionary = mSuggest.getMainDictionary();
+ }
+ if (mDictionary == null) {
+ // Can't access dictionary. Assume privacy threat.
+ return true;
+ }
+ return !(mDictionary.isValidWord(word));
+ }
+ // No letters, no numbers. Punctuation, space, or something else.
+ return false;
+ }
+
+ private void onWordComplete(String word) {
+ final boolean isPrivacyThreat = isPrivacyThreat(word);
+ flushEventQueue(isPrivacyThreat);
+ if (isPrivacyThreat) {
+ mLoggingFrequencyState.onWordNotLogged();
+ } else {
+ mLoggingFrequencyState.onWordLogged();
}
}
/**
- * Represents a category of logging events that share the same subfield structure.
+ * Write out enqueued LogEvents to the log, possibly dropping privacy sensitive events.
*/
- private static enum LogGroup {
- MOTION_EVENT("m"),
- KEY("k"),
- CORRECTION("c"),
- STATE_CHANGE("s"),
- UNSTRUCTURED("u");
-
- private final String mLogString;
-
- private LogGroup(final String logString) {
- mLogString = logString;
- }
- }
-
- public void logMotionEvent(final int action, final long eventTime, final int id,
- final int x, final int y, final float size, final float pressure) {
- final String eventTag;
- switch (action) {
- case MotionEvent.ACTION_CANCEL: eventTag = "[Cancel]"; break;
- case MotionEvent.ACTION_UP: eventTag = "[Up]"; break;
- case MotionEvent.ACTION_DOWN: eventTag = "[Down]"; break;
- case MotionEvent.ACTION_POINTER_UP: eventTag = "[PointerUp]"; break;
- case MotionEvent.ACTION_POINTER_DOWN: eventTag = "[PointerDown]"; break;
- case MotionEvent.ACTION_MOVE: eventTag = "[Move]"; break;
- case MotionEvent.ACTION_OUTSIDE: eventTag = "[Outside]"; break;
- default: eventTag = "[Action" + action + "]"; break;
- }
- if (!TextUtils.isEmpty(eventTag)) {
- final StringBuilder sb = new StringBuilder();
- sb.append(eventTag);
- sb.append('\t'); sb.append(eventTime);
- sb.append('\t'); sb.append(id);
- sb.append('\t'); sb.append(x);
- sb.append('\t'); sb.append(y);
- sb.append('\t'); sb.append(size);
- sb.append('\t'); sb.append(pressure);
- write(LogGroup.MOTION_EVENT, sb.toString());
- }
- }
-
- public void logKeyEvent(final int code, final int x, final int y) {
- final StringBuilder sb = new StringBuilder();
- sb.append(Keyboard.printableCode(code));
- sb.append('\t'); sb.append(x);
- sb.append('\t'); sb.append(y);
- write(LogGroup.KEY, sb.toString());
- }
-
- public void logCorrection(final String subgroup, final String before, final String after,
- final int position) {
- final StringBuilder sb = new StringBuilder();
- sb.append(subgroup);
- sb.append('\t'); sb.append(before);
- sb.append('\t'); sb.append(after);
- sb.append('\t'); sb.append(position);
- write(LogGroup.CORRECTION, sb.toString());
- }
-
- public void logStateChange(final String subgroup, final String details) {
- write(LogGroup.STATE_CHANGE, subgroup + "\t" + details);
- }
-
- public static class UnsLogGroup {
- private static final boolean DEFAULT_ENABLED = true;
-
- private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED;
- private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_COMMITTEXT_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_PERFORMEDITORACTION_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_PICKSUGGESTIONMANUALLY_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_REVERTCOMMIT_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean LATINIME_REVERTSWAPPUNCTUATION_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_SENDKEYCODEPOINT_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED;
- private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED = DEFAULT_ENABLED;
- private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean
- POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED;
- private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED;
- private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED;
- private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED
- = DEFAULT_ENABLED;
- private static final boolean SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED = DEFAULT_ENABLED;
- }
-
- public static void logUnstructured(String logGroup, final String details) {
- // TODO: improve performance by making entire class static and/or implementing natively
- getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details);
- }
-
- private void write(final LogGroup logGroup, final String log) {
- // TODO: rewrite in native for better performance
- mLoggingHandler.post(new Runnable() {
- @Override
- public void run() {
- final long currentTime = System.currentTimeMillis();
- final long upTime = SystemClock.uptimeMillis();
- final StringBuilder builder = new StringBuilder();
- builder.append(currentTime);
- builder.append('\t'); builder.append(upTime);
- builder.append('\t'); builder.append(logGroup.mLogString);
- builder.append('\t'); builder.append(log);
- builder.append('\n');
- if (DEBUG) {
- Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log);
- }
- final String s = builder.toString();
- if (mLogFileManager.append(s)) {
- // success
- } else {
- if (DEBUG) {
- Log.w(TAG, "Unable to write to log.");
+ /* package for test */ synchronized void flushEventQueue(
+ boolean removePotentiallyPrivateEvents) {
+ if (isAllowedToLog()) {
+ mCurrentLogUnit.setRemovePotentiallyPrivateEvents(removePotentiallyPrivateEvents);
+ mLoggingHandler.post(mCurrentLogUnit);
+ }
+ mCurrentLogUnit = new LogUnit();
+ }
+
+ private synchronized void outputEvent(final String[] keys, final Object[] values) {
+ try {
+ mJsonWriter.beginObject();
+ mJsonWriter.name(CURRENT_TIME_KEY).value(System.currentTimeMillis());
+ mJsonWriter.name(UPTIME_KEY).value(SystemClock.uptimeMillis());
+ mJsonWriter.name(EVENT_TYPE_KEY).value(keys[0]);
+ final int length = values.length;
+ for (int i = 0; i < length; i++) {
+ mJsonWriter.name(keys[i + 1]);
+ Object value = values[i];
+ if (value instanceof String) {
+ mJsonWriter.value((String) value);
+ } else if (value instanceof Number) {
+ mJsonWriter.value((Number) value);
+ } else if (value instanceof Boolean) {
+ mJsonWriter.value((Boolean) value);
+ } else if (value instanceof CompletionInfo[]) {
+ CompletionInfo[] ci = (CompletionInfo[]) value;
+ mJsonWriter.beginArray();
+ for (int j = 0; j < ci.length; j++) {
+ mJsonWriter.value(ci[j].toString());
}
- // perhaps logfile was deleted. try to recreate and relog.
- try {
- mLogFileManager.createLogFile(PreferenceManager
- .getDefaultSharedPreferences(mIms));
- mLogFileManager.append(s);
- } catch (IOException e) {
- e.printStackTrace();
+ mJsonWriter.endArray();
+ } else if (value instanceof SharedPreferences) {
+ SharedPreferences prefs = (SharedPreferences) value;
+ mJsonWriter.beginObject();
+ for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
+ mJsonWriter.name(entry.getKey());
+ final Object innerValue = entry.getValue();
+ if (innerValue == null) {
+ mJsonWriter.nullValue();
+ } else if (innerValue instanceof Boolean) {
+ mJsonWriter.value((Boolean) innerValue);
+ } else if (innerValue instanceof Number) {
+ mJsonWriter.value((Number) innerValue);
+ } else {
+ mJsonWriter.value(innerValue.toString());
+ }
}
+ mJsonWriter.endObject();
+ } else if (value instanceof Key[]) {
+ Key[] keyboardKeys = (Key[]) value;
+ mJsonWriter.beginArray();
+ for (Key keyboardKey : keyboardKeys) {
+ mJsonWriter.beginObject();
+ mJsonWriter.name("code").value(keyboardKey.mCode);
+ mJsonWriter.name("altCode").value(keyboardKey.mAltCode);
+ mJsonWriter.name("x").value(keyboardKey.mX);
+ mJsonWriter.name("y").value(keyboardKey.mY);
+ mJsonWriter.name("w").value(keyboardKey.mWidth);
+ mJsonWriter.name("h").value(keyboardKey.mHeight);
+ mJsonWriter.endObject();
+ }
+ mJsonWriter.endArray();
+ } else if (value instanceof SuggestedWords) {
+ SuggestedWords words = (SuggestedWords) value;
+ mJsonWriter.beginObject();
+ mJsonWriter.name("typedWordValid").value(words.mTypedWordValid);
+ mJsonWriter.name("hasAutoCorrectionCandidate")
+ .value(words.mHasAutoCorrectionCandidate);
+ mJsonWriter.name("isPunctuationSuggestions")
+ .value(words.mIsPunctuationSuggestions);
+ mJsonWriter.name("isObsoleteSuggestions")
+ .value(words.mIsObsoleteSuggestions);
+ mJsonWriter.name("isPrediction")
+ .value(words.mIsPrediction);
+ mJsonWriter.name("words");
+ mJsonWriter.beginArray();
+ final int size = words.size();
+ for (int j = 0; j < size; j++) {
+ SuggestedWordInfo wordInfo = words.getWordInfo(j);
+ mJsonWriter.value(wordInfo.toString());
+ }
+ mJsonWriter.endArray();
+ mJsonWriter.endObject();
+ } else if (value == null) {
+ mJsonWriter.nullValue();
+ } else {
+ Log.w(TAG, "Unrecognized type to be logged: " +
+ (value == null ? "<null>" : value.getClass().getName()));
+ mJsonWriter.nullValue();
}
}
- });
+ mJsonWriter.endObject();
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.w(TAG, "Error in JsonWriter; disabling logging");
+ try {
+ mJsonWriter.close();
+ } catch (IllegalStateException e1) {
+ // assume that this is just the json not being terminated properly.
+ // ignore
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ } finally {
+ mJsonWriter = NULL_JSON_WRITER;
+ }
+ }
}
- public void clearAll() {
- mLoggingHandler.post(new Runnable() {
- @Override
- public void run() {
- if (DEBUG) {
- Log.d(TAG, "Delete log file.");
+ private static class LogUnit implements Runnable {
+ private final List<String[]> mKeysList = new ArrayList<String[]>();
+ private final List<Object[]> mValuesList = new ArrayList<Object[]>();
+ private final List<Boolean> mIsPotentiallyPrivate = new ArrayList<Boolean>();
+ private boolean mRemovePotentiallyPrivateEvents = true;
+
+ private void addLogAtom(final String[] keys, final Object[] values,
+ final Boolean isPotentiallyPrivate) {
+ mKeysList.add(keys);
+ mValuesList.add(values);
+ mIsPotentiallyPrivate.add(isPotentiallyPrivate);
+ }
+
+ void setRemovePotentiallyPrivateEvents(boolean removePotentiallyPrivateEvents) {
+ mRemovePotentiallyPrivateEvents = removePotentiallyPrivateEvents;
+ }
+
+ @Override
+ public void run() {
+ final int numAtoms = mKeysList.size();
+ for (int atomIndex = 0; atomIndex < numAtoms; atomIndex++) {
+ if (mRemovePotentiallyPrivateEvents && mIsPotentiallyPrivate.get(atomIndex)) {
+ continue;
}
- mLogFileManager.reset();
+ final String[] keys = mKeysList.get(atomIndex);
+ final Object[] values = mValuesList.get(atomIndex);
+ ResearchLogger.getInstance().outputEvent(keys, values);
}
- });
+ }
}
- /* package */ LogFileManager getLogFileManager() {
- return mLogFileManager;
+ private static int scrubDigitFromCodePoint(int codePoint) {
+ return Character.isDigit(codePoint) ? DIGIT_REPLACEMENT_CODEPOINT : codePoint;
}
- @Override
- public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- if (key == null || prefs == null) {
- return;
+ /* package for test */ static String scrubDigitsFromString(String s) {
+ StringBuilder sb = null;
+ final int length = s.length();
+ for (int i = 0; i < length; i = s.offsetByCodePoints(i, 1)) {
+ final int codePoint = Character.codePointAt(s, i);
+ if (Character.isDigit(codePoint)) {
+ if (sb == null) {
+ sb = new StringBuilder(length);
+ sb.append(s.substring(0, i));
+ }
+ sb.appendCodePoint(DIGIT_REPLACEMENT_CODEPOINT);
+ } else {
+ if (sb != null) {
+ sb.appendCodePoint(codePoint);
+ }
+ }
}
- sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false);
- }
-
- public static void keyboardState_onCancelInput(final boolean isSinglePointer,
- final KeyboardState keyboardState) {
- if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) {
- final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState;
- logUnstructured("KeyboardState_onCancelInput", s);
+ if (sb == null) {
+ return s;
+ } else {
+ return sb.toString();
}
}
- public static void keyboardState_onCodeInput(
- final int code, final boolean isSinglePointer, final int autoCaps,
- final KeyboardState keyboardState) {
- if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) {
- final String s = "onCodeInput: code=" + Keyboard.printableCode(code)
- + " single=" + isSinglePointer
- + " autoCaps=" + autoCaps + " " + keyboardState;
- logUnstructured("KeyboardState_onCodeInput", s);
+ private String scrubWord(String word) {
+ if (mDictionary == null) {
+ return WORD_REPLACEMENT_STRING;
+ }
+ if (mDictionary.isValidWord(word)) {
+ return word;
}
+ return WORD_REPLACEMENT_STRING;
}
- public static void keyboardState_onLongPressTimeout(final int code,
- final KeyboardState keyboardState) {
- if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) {
- final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " "
- + keyboardState;
- logUnstructured("KeyboardState_onLongPressTimeout", s);
+ private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = {
+ "LatinKeyboardViewProcessMotionEvent", "action", "eventTime", "id", "x", "y", "size",
+ "pressure"
+ };
+ public static void latinKeyboardView_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 float size = me.getSize(index);
+ final float pressure = me.getPressure(index);
+ final Object[] values = {
+ actionString, eventTime, id, x, y, size, pressure
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT, values);
}
}
- public static void keyboardState_onPressKey(final int code,
- final KeyboardState keyboardState) {
- if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) {
- final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " "
- + keyboardState;
- logUnstructured("KeyboardState_onPressKey", s);
- }
+ private static final String[] EVENTKEYS_LATINIME_ONCODEINPUT = {
+ "LatinIMEOnCodeInput", "code", "x", "y"
+ };
+ public static void latinIME_onCodeInput(final int code, final int x, final int y) {
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(code)), x, y
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONCODEINPUT, values);
}
- public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code,
- final boolean withSliding) {
- if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) {
- final String s = "onReleaseKey: code=" + Keyboard.printableCode(code)
- + " sliding=" + withSliding + " " + keyboardState;
- logUnstructured("KeyboardState_onReleaseKey", s);
- }
+ private static final String[] EVENTKEYS_CORRECTION = {
+ "LogCorrection", "subgroup", "before", "after", "position"
+ };
+ public static void logCorrection(final String subgroup, final String before, final String after,
+ final int position) {
+ final Object[] values = {
+ subgroup, scrubDigitsFromString(before), scrubDigitsFromString(after), position
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_CORRECTION, values);
}
+ private static final String[] EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION = {
+ "LatinIMECommitCurrentAutoCorrection", "typedWord", "autoCorrection"
+ };
public static void latinIME_commitCurrentAutoCorrection(final String typedWord,
final String autoCorrection) {
- if (UnsLogGroup.LATINIME_COMMITCURRENTAUTOCORRECTION_ENABLED) {
- if (typedWord.equals(autoCorrection)) {
- getInstance().logCorrection("[----]", typedWord, autoCorrection, -1);
- } else {
- getInstance().logCorrection("[Auto]", typedWord, autoCorrection, -1);
- }
- }
+ final Object[] values = {
+ scrubDigitsFromString(typedWord), scrubDigitsFromString(autoCorrection)
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_LATINIME_COMMITCURRENTAUTOCORRECTION, values);
}
+ private static final String[] EVENTKEYS_LATINIME_COMMITTEXT = {
+ "LatinIMECommitText", "typedWord"
+ };
public static void latinIME_commitText(final CharSequence typedWord) {
- if (UnsLogGroup.LATINIME_COMMITTEXT_ENABLED) {
- logUnstructured("LatinIME_commitText", typedWord.toString());
- }
+ final String scrubbedWord = scrubDigitsFromString(typedWord.toString());
+ final Object[] values = {
+ scrubbedWord
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_COMMITTEXT, values);
+ researchLogger.onWordComplete(scrubbedWord);
}
+ private static final String[] EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT = {
+ "LatinIMEDeleteSurroundingText", "length"
+ };
public static void latinIME_deleteSurroundingText(final int length) {
- if (UnsLogGroup.LATINIME_DELETESURROUNDINGTEXT_ENABLED) {
- logUnstructured("LatinIME_deleteSurroundingText", String.valueOf(length));
- }
+ final Object[] values = {
+ length
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_DELETESURROUNDINGTEXT, values);
}
+ private static final String[] EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD = {
+ "LatinIMEDoubleSpaceAutoPeriod"
+ };
public static void latinIME_doubleSpaceAutoPeriod() {
- if (UnsLogGroup.LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED) {
- logUnstructured("LatinIME_doubleSpaceAutoPeriod", "");
- }
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_DOUBLESPACEAUTOPERIOD, EVENTKEYS_NULLVALUES);
}
+ private static final String[] EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS = {
+ "LatinIMEOnDisplayCompletions", "applicationSpecifiedCompletions"
+ };
public static void latinIME_onDisplayCompletions(
final CompletionInfo[] applicationSpecifiedCompletions) {
- if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) {
- final StringBuilder builder = new StringBuilder();
- builder.append("Received completions:");
- if (applicationSpecifiedCompletions != null) {
- for (int i = 0; i < applicationSpecifiedCompletions.length; i++) {
- builder.append(" #");
- builder.append(i);
- builder.append(": ");
- builder.append(applicationSpecifiedCompletions[i]);
- builder.append("\n");
+ final Object[] values = {
+ applicationSpecifiedCompletions
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONDISPLAYCOMPLETIONS,
+ values);
+ }
+
+ /* package */ static boolean getAndClearLatinIMEExpectingUpdateSelection() {
+ boolean returnValue = sLatinIMEExpectingUpdateSelection;
+ sLatinIMEExpectingUpdateSelection = false;
+ return returnValue;
+ }
+
+ private static final String[] EVENTKEYS_LATINIME_ONWINDOWHIDDEN = {
+ "LatinIMEOnWindowHidden", "isTextTruncated", "text"
+ };
+ public static void latinIME_onWindowHidden(final int savedSelectionStart,
+ final int savedSelectionEnd, final InputConnection ic) {
+ if (ic != null) {
+ ic.beginBatchEdit();
+ ic.performContextMenuAction(android.R.id.selectAll);
+ CharSequence charSequence = ic.getSelectedText(0);
+ ic.setSelection(savedSelectionStart, savedSelectionEnd);
+ ic.endBatchEdit();
+ sLatinIMEExpectingUpdateSelection = true;
+ final Object[] values = new Object[2];
+ if (OUTPUT_ENTIRE_BUFFER) {
+ if (TextUtils.isEmpty(charSequence)) {
+ values[0] = false;
+ values[1] = "";
+ } else {
+ if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) {
+ int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE;
+ // do not cut in the middle of a supplementary character
+ final char c = charSequence.charAt(length - 1);
+ if (Character.isHighSurrogate(c)) {
+ length--;
+ }
+ final CharSequence truncatedCharSequence = charSequence.subSequence(0,
+ length);
+ values[0] = true;
+ values[1] = truncatedCharSequence.toString();
+ } else {
+ values[0] = false;
+ values[1] = charSequence.toString();
+ }
}
+ } else {
+ values[0] = true;
+ values[1] = "";
}
- logUnstructured("LatinIME_onDisplayCompletions", builder.toString());
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueueEvent(EVENTKEYS_LATINIME_ONWINDOWHIDDEN, values);
+ researchLogger.flushEventQueue(true); // Play it safe. Remove privacy-sensitive events.
}
}
+ private static final String[] EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL = {
+ "LatinIMEOnStartInputViewInternal", "uuid", "packageName", "inputType", "imeOptions",
+ "fieldId", "display", "model", "prefs", "outputFormatVersion"
+ };
public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
final SharedPreferences prefs) {
- if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) {
- final StringBuilder builder = new StringBuilder();
- builder.append("onStartInputView: editorInfo:");
- builder.append("\tinputType=");
- builder.append(Integer.toHexString(editorInfo.inputType));
- builder.append("\timeOptions=");
- builder.append(Integer.toHexString(editorInfo.imeOptions));
- builder.append("\tdisplay="); builder.append(Build.DISPLAY);
- builder.append("\tmodel="); builder.append(Build.MODEL);
- for (Map.Entry<String,?> entry : prefs.getAll().entrySet()) {
- builder.append("\t" + entry.getKey());
- Object value = entry.getValue();
- builder.append("=" + ((value == null) ? "<null>" : value.toString()));
- }
- logUnstructured("LatinIME_onStartInputViewInternal", builder.toString());
+ if (editorInfo != null) {
+ final Object[] values = {
+ getUUID(prefs), editorInfo.packageName, Integer.toHexString(editorInfo.inputType),
+ Integer.toHexString(editorInfo.imeOptions), editorInfo.fieldId, Build.DISPLAY,
+ Build.MODEL, prefs, OUTPUT_FORMAT_VERSION
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_ONSTARTINPUTVIEWINTERNAL, values);
}
}
+ 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 static final String[] EVENTKEYS_LATINIME_ONUPDATESELECTION = {
+ "LatinIMEOnUpdateSelection", "lastSelectionStart", "lastSelectionEnd", "oldSelStart",
+ "oldSelEnd", "newSelStart", "newSelEnd", "composingSpanStart", "composingSpanEnd",
+ "expectingUpdateSelection", "expectingUpdateSelectionFromLogger", "context"
+ };
public static void latinIME_onUpdateSelection(final int lastSelectionStart,
final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd,
final int newSelStart, final int newSelEnd, final int composingSpanStart,
- final int composingSpanEnd) {
- if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) {
- final String s = "onUpdateSelection: oss=" + oldSelStart
- + ", ose=" + oldSelEnd
- + ", lss=" + lastSelectionStart
- + ", lse=" + lastSelectionEnd
- + ", nss=" + newSelStart
- + ", nse=" + newSelEnd
- + ", cs=" + composingSpanStart
- + ", ce=" + composingSpanEnd;
- logUnstructured("LatinIME_onUpdateSelection", s);
+ final int composingSpanEnd, final boolean expectingUpdateSelection,
+ final boolean expectingUpdateSelectionFromLogger,
+ final RichInputConnection connection) {
+ String word = "";
+ if (connection != null) {
+ Range range = connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1);
+ if (range != null) {
+ word = range.mWord;
+ }
}
+ final ResearchLogger researchLogger = getInstance();
+ final String scrubbedWord = researchLogger.scrubWord(word);
+ final Object[] values = {
+ lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart,
+ newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection,
+ expectingUpdateSelectionFromLogger, scrubbedWord
+ };
+ researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values);
}
+ private static final String[] EVENTKEYS_LATINIME_PERFORMEDITORACTION = {
+ "LatinIMEPerformEditorAction", "imeActionNext"
+ };
public static void latinIME_performEditorAction(final int imeActionNext) {
- if (UnsLogGroup.LATINIME_PERFORMEDITORACTION_ENABLED) {
- logUnstructured("LatinIME_performEditorAction", String.valueOf(imeActionNext));
- }
+ final Object[] values = {
+ imeActionNext
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_PERFORMEDITORACTION, values);
}
+ private static final String[] EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION = {
+ "LatinIMEPickApplicationSpecifiedCompletion", "index", "text", "x", "y"
+ };
public static void latinIME_pickApplicationSpecifiedCompletion(final int index,
- final CharSequence text, int x, int y) {
- if (UnsLogGroup.LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION_ENABLED) {
- final String s = String.valueOf(index) + '\t' + text + '\t' + x + '\t' + y;
- logUnstructured("LatinIME_pickApplicationSpecifiedCompletion", s);
- }
+ final CharSequence cs, int x, int y) {
+ final Object[] values = {
+ index, cs, x, y
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values);
}
+ private static final String[] EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY = {
+ "LatinIMEPickSuggestionManually", "replacedWord", "index", "suggestion", "x", "y"
+ };
public static void latinIME_pickSuggestionManually(final String replacedWord,
final int index, CharSequence suggestion, int x, int y) {
- if (UnsLogGroup.LATINIME_PICKSUGGESTIONMANUALLY_ENABLED) {
- final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y;
- logUnstructured("LatinIME_pickSuggestionManually", s);
- }
+ final Object[] values = {
+ scrubDigitsFromString(replacedWord), index, suggestion == null ? null :
+ scrubDigitsFromString(suggestion.toString()), x, y
+ };
+ final ResearchLogger researchLogger = getInstance();
+ researchLogger.enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY,
+ values);
}
+ private static final String[] EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION = {
+ "LatinIMEPunctuationSuggestion", "index", "suggestion", "x", "y"
+ };
public static void latinIME_punctuationSuggestion(final int index,
final CharSequence suggestion, int x, int y) {
- if (UnsLogGroup.LATINIME_PICKPUNCTUATIONSUGGESTION_ENABLED) {
- final String s = String.valueOf(index) + '\t' + suggestion + '\t' + x + '\t' + y;
- logUnstructured("LatinIME_pickPunctuationSuggestion", s);
- }
+ final Object[] values = {
+ index, suggestion, x, y
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values);
}
+ private static final String[] EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT = {
+ "LatinIMERevertDoubleSpaceWhileInBatchEdit"
+ };
public static void latinIME_revertDoubleSpaceWhileInBatchEdit() {
- if (UnsLogGroup.LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT_ENABLED) {
- logUnstructured("LatinIME_revertDoubleSpaceWhileInBatchEdit", "");
- }
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_REVERTDOUBLESPACEWHILEINBATCHEDIT,
+ EVENTKEYS_NULLVALUES);
}
+ private static final String[] EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION = {
+ "LatinIMERevertSwapPunctuation"
+ };
public static void latinIME_revertSwapPunctuation() {
- if (UnsLogGroup.LATINIME_REVERTSWAPPUNCTUATION_ENABLED) {
- logUnstructured("LatinIME_revertSwapPunctuation", "");
- }
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_REVERTSWAPPUNCTUATION, EVENTKEYS_NULLVALUES);
}
+ private static final String[] EVENTKEYS_LATINIME_SENDKEYCODEPOINT = {
+ "LatinIMESendKeyCodePoint", "code"
+ };
public static void latinIME_sendKeyCodePoint(final int code) {
- if (UnsLogGroup.LATINIME_SENDKEYCODEPOINT_ENABLED) {
- logUnstructured("LatinIME_sendKeyCodePoint", String.valueOf(code));
- }
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(code))
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_SENDKEYCODEPOINT, values);
}
+ private static final String[] EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT = {
+ "LatinIMESwapSwapperAndSpaceWhileInBatchEdit"
+ };
public static void latinIME_swapSwapperAndSpaceWhileInBatchEdit() {
- if (UnsLogGroup.LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT_ENABLED) {
- logUnstructured("latinIME_swapSwapperAndSpaceWhileInBatchEdit", "");
- }
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWAPSWAPPERANDSPACEWHILEINBATCHEDIT,
+ EVENTKEYS_NULLVALUES);
}
+ private static final String[] EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW = {
+ "LatinIMESwitchToKeyboardView"
+ };
public static void latinIME_switchToKeyboardView() {
- if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) {
- final String s = "Switch to keyboard view.";
- logUnstructured("LatinIME_switchToKeyboardView", s);
- }
+ getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES);
}
+ private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = {
+ "LatinKeyboardViewOnLongPress"
+ };
public static void latinKeyboardView_onLongPress() {
- if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) {
- final String s = "long press detected";
- logUnstructured("LatinKeyboardView_onLongPress", s);
- }
- }
-
- public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action,
- long eventTime, int index, int id, int x, int y) {
- if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) {
- final float size = me.getSize(index);
- final float pressure = me.getPressure(index);
- if (action != MotionEvent.ACTION_MOVE) {
- getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure);
- }
- }
+ getInstance().enqueueEvent(EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS, EVENTKEYS_NULLVALUES);
}
+ private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD = {
+ "LatinKeyboardViewSetKeyboard", "elementId", "locale", "orientation", "width",
+ "modeName", "action", "navigateNext", "navigatePrevious", "clobberSettingsKey",
+ "passwordInput", "shortcutKeyEnabled", "hasShortcutKey", "languageSwitchKeyEnabled",
+ "isMultiLine", "tw", "th", "keys"
+ };
public static void latinKeyboardView_setKeyboard(final Keyboard keyboard) {
- if (UnsLogGroup.LATINKEYBOARDVIEW_SETKEYBOARD_ENABLED) {
- StringBuilder builder = new StringBuilder();
- builder.append("id=");
- builder.append(keyboard.mId);
- builder.append("\tw=");
- builder.append(keyboard.mOccupiedWidth);
- builder.append("\th=");
- builder.append(keyboard.mOccupiedHeight);
- builder.append("\tkeys=[");
- boolean first = true;
- for (Key key : keyboard.mKeys) {
- if (first) {
- first = false;
- } else {
- builder.append(",");
- }
- builder.append("{code:");
- builder.append(key.mCode);
- builder.append(",altCode:");
- builder.append(key.mAltCode);
- builder.append(",x:");
- builder.append(key.mX);
- builder.append(",y:");
- builder.append(key.mY);
- builder.append(",w:");
- builder.append(key.mWidth);
- builder.append(",h:");
- builder.append(key.mHeight);
- builder.append("}");
- }
- builder.append("]");
- logUnstructured("LatinKeyboardView_setKeyboard", builder.toString());
+ if (keyboard != null) {
+ final KeyboardId kid = keyboard.mId;
+ final boolean isPasswordView = kid.passwordInput();
+ final Object[] values = {
+ KeyboardId.elementIdToName(kid.mElementId),
+ kid.mLocale + ":" + kid.mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
+ kid.mOrientation,
+ kid.mWidth,
+ KeyboardId.modeName(kid.mMode),
+ kid.imeAction(),
+ kid.navigateNext(),
+ kid.navigatePrevious(),
+ kid.mClobberSettingsKey,
+ isPasswordView,
+ kid.mShortcutKeyEnabled,
+ kid.mHasShortcutKey,
+ kid.mLanguageSwitchKeyEnabled,
+ kid.isMultiLine(),
+ keyboard.mOccupiedWidth,
+ keyboard.mOccupiedHeight,
+ keyboard.mKeys
+ };
+ getInstance().enqueueEvent(EVENTKEYS_LATINKEYBOARDVIEW_SETKEYBOARD, values);
+ getInstance().setIsPasswordView(isPasswordView);
}
}
+ private static final String[] EVENTKEYS_LATINIME_REVERTCOMMIT = {
+ "LatinIMERevertCommit", "originallyTypedWord"
+ };
public static void latinIME_revertCommit(final String originallyTypedWord) {
- if (UnsLogGroup.LATINIME_REVERTCOMMIT_ENABLED) {
- logUnstructured("LatinIME_revertCommit", originallyTypedWord);
- }
+ final Object[] values = {
+ originallyTypedWord
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_LATINIME_REVERTCOMMIT, values);
}
+ private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT = {
+ "PointerTrackerCallListenerOnCancelInput"
+ };
public static void pointerTracker_callListenerOnCancelInput() {
- final String s = "onCancelInput";
- if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) {
- logUnstructured("PointerTracker_callListenerOnCancelInput", s);
- }
+ getInstance().enqueueEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCANCELINPUT,
+ EVENTKEYS_NULLVALUES);
}
+ private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT = {
+ "PointerTrackerCallListenerOnCodeInput", "code", "outputText", "x", "y",
+ "ignoreModifierKey", "altersCode", "isEnabled"
+ };
public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x,
final int y, final boolean ignoreModifierKey, final boolean altersCode,
final int code) {
- if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) {
- final String s = "onCodeInput: " + Keyboard.printableCode(code)
- + " text=" + key.mOutputText + " x=" + x + " y=" + y
- + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode
- + " enabled=" + key.isEnabled();
- logUnstructured("PointerTracker_callListenerOnCodeInput", s);
- }
- }
-
- public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(
- final Key key, final boolean ignoreModifierKey) {
- if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) {
- final String s = "onPress : " + KeyDetector.printableCode(key)
- + " ignoreModifier=" + ignoreModifierKey
- + " enabled=" + key.isEnabled();
- logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s);
+ if (key != null) {
+ CharSequence outputText = key.mOutputText;
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(code)), outputText == null ? null
+ : scrubDigitsFromString(outputText.toString()),
+ x, y, ignoreModifierKey, altersCode, key.isEnabled()
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values);
}
}
+ private static final String[] EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE = {
+ "PointerTrackerCallListenerOnRelease", "code", "withSliding", "ignoreModifierKey",
+ "isEnabled"
+ };
public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode,
final boolean withSliding, final boolean ignoreModifierKey) {
- if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) {
- final String s = "onRelease : " + Keyboard.printableCode(primaryCode)
- + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey
- + " enabled="+ key.isEnabled();
- logUnstructured("PointerTracker_callListenerOnRelease", s);
+ if (key != null) {
+ final Object[] values = {
+ Keyboard.printableCode(scrubDigitFromCodePoint(primaryCode)), withSliding,
+ ignoreModifierKey, key.isEnabled()
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_POINTERTRACKER_CALLLISTENERONRELEASE, values);
}
}
+ private static final String[] EVENTKEYS_POINTERTRACKER_ONDOWNEVENT = {
+ "PointerTrackerOnDownEvent", "deltaT", "distanceSquared"
+ };
public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) {
- if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) {
- final String s = "onDownEvent: ignore potential noise: time=" + deltaT
- + " distance=" + distanceSquared;
- logUnstructured("PointerTracker_onDownEvent", s);
- }
+ final Object[] values = {
+ deltaT, distanceSquared
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_POINTERTRACKER_ONDOWNEVENT, values);
}
+ private static final String[] EVENTKEYS_POINTERTRACKER_ONMOVEEVENT = {
+ "PointerTrackerOnMoveEvent", "x", "y", "lastX", "lastY"
+ };
public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX,
final int lastY) {
- if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) {
- final String s = String.format("onMoveEvent: sudden move is translated to "
- + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y);
- logUnstructured("PointerTracker_onMoveEvent", s);
- }
+ final Object[] values = {
+ x, y, lastX, lastY
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_POINTERTRACKER_ONMOVEEVENT, values);
}
+ private static final String[] EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT = {
+ "SuddenJumpingTouchEventHandlerOnTouchEvent", "motionEvent"
+ };
public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) {
- if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) {
- final String s = "onTouchEvent: ignore sudden jump " + me;
- logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s);
+ if (me != null) {
+ final Object[] values = {
+ me.toString()
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(
+ EVENTKEYS_SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT, values);
}
}
- public static void suggestionsView_setSuggestions(final SuggestedWords mSuggestedWords) {
- if (UnsLogGroup.SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED) {
- logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString());
+ private static final String[] EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS = {
+ "SuggestionsViewSetSuggestions", "suggestedWords"
+ };
+ public static void suggestionsView_setSuggestions(final SuggestedWords suggestedWords) {
+ if (suggestedWords != null) {
+ final Object[] values = {
+ suggestedWords
+ };
+ getInstance().enqueuePotentiallyPrivateEvent(EVENTKEYS_SUGGESTIONSVIEW_SETSUGGESTIONS,
+ values);
}
}
-} \ No newline at end of file
+
+ private static final String[] EVENTKEYS_USER_TIMESTAMP = {
+ "UserTimestamp"
+ };
+ public void userTimestamp() {
+ getInstance().enqueueEvent(EVENTKEYS_USER_TIMESTAMP, EVENTKEYS_NULLVALUES);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
new file mode 100644
index 000000000..40d327ebb
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CorrectionInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
+import android.view.inputmethod.InputConnection;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.define.ProductionFlag;
+
+import java.util.regex.Pattern;
+
+/**
+ * Wrapper for InputConnection to simplify interaction
+ */
+public class RichInputConnection {
+ private static final String TAG = RichInputConnection.class.getSimpleName();
+ private static final boolean DBG = false;
+ // Provision for a long word pair and a separator
+ private static final int LOOKBACK_CHARACTER_NUM = BinaryDictionary.MAX_WORD_LENGTH * 2 + 1;
+ private static final Pattern spaceRegex = Pattern.compile("\\s+");
+ private static final int INVALID_CURSOR_POSITION = -1;
+
+ InputConnection mIC;
+ int mNestLevel;
+ public RichInputConnection() {
+ mIC = null;
+ mNestLevel = 0;
+ }
+
+ public void beginBatchEdit(final InputConnection newInputConnection) {
+ if (++mNestLevel == 1) {
+ mIC = newInputConnection;
+ if (null != mIC) mIC.beginBatchEdit();
+ } else {
+ if (DBG) {
+ throw new RuntimeException("Nest level too deep");
+ } else {
+ Log.e(TAG, "Nest level too deep : " + mNestLevel);
+ }
+ }
+ }
+ public void endBatchEdit() {
+ if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+ if (--mNestLevel == 0 && null != mIC) mIC.endBatchEdit();
+ }
+
+ private void checkBatchEdit() {
+ if (mNestLevel != 1) {
+ // TODO: exception instead
+ Log.e(TAG, "Batch edit level incorrect : " + mNestLevel);
+ Log.e(TAG, Utils.getStackTrace(4));
+ }
+ }
+
+ public void finishComposingText() {
+ checkBatchEdit();
+ if (null != mIC) mIC.finishComposingText();
+ }
+
+ public void commitText(final CharSequence text, final int i) {
+ checkBatchEdit();
+ if (null != mIC) mIC.commitText(text, i);
+ }
+
+ public int getCursorCapsMode(final int inputType) {
+ if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
+ return mIC.getCursorCapsMode(inputType);
+ }
+
+ public CharSequence getTextBeforeCursor(final int i, final int j) {
+ if (null != mIC) return mIC.getTextBeforeCursor(i, j);
+ return null;
+ }
+
+ public CharSequence getTextAfterCursor(final int i, final int j) {
+ if (null != mIC) return mIC.getTextAfterCursor(i, j);
+ return null;
+ }
+
+ public void deleteSurroundingText(final int i, final int j) {
+ checkBatchEdit();
+ if (null != mIC) mIC.deleteSurroundingText(i, j);
+ }
+
+ public void performEditorAction(final int actionId) {
+ if (null != mIC) mIC.performEditorAction(actionId);
+ }
+
+ public void sendKeyEvent(final KeyEvent keyEvent) {
+ checkBatchEdit();
+ if (null != mIC) mIC.sendKeyEvent(keyEvent);
+ }
+
+ public void setComposingText(final CharSequence text, final int i) {
+ checkBatchEdit();
+ if (null != mIC) mIC.setComposingText(text, i);
+ }
+
+ public void setSelection(final int from, final int to) {
+ checkBatchEdit();
+ if (null != mIC) mIC.setSelection(from, to);
+ }
+
+ public void commitCorrection(final CorrectionInfo correctionInfo) {
+ checkBatchEdit();
+ if (null != mIC) mIC.commitCorrection(correctionInfo);
+ }
+
+ public void commitCompletion(final CompletionInfo completionInfo) {
+ checkBatchEdit();
+ if (null != mIC) mIC.commitCompletion(completionInfo);
+ }
+
+ public CharSequence getPreviousWord(final String sentenceSeperators) {
+ //TODO: Should fix this. This could be slow!
+ if (null == mIC) return null;
+ CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
+ return getPreviousWord(prev, sentenceSeperators);
+ }
+
+ /**
+ * Represents a range of text, relative to the current cursor position.
+ */
+ public static class Range {
+ /** Characters before selection start */
+ public final int mCharsBefore;
+
+ /**
+ * Characters after selection start, including one trailing word
+ * separator.
+ */
+ public final int mCharsAfter;
+
+ /** The actual characters that make up a word */
+ public final String mWord;
+
+ public Range(int charsBefore, int charsAfter, String word) {
+ if (charsBefore < 0 || charsAfter < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ this.mCharsBefore = charsBefore;
+ this.mCharsAfter = charsAfter;
+ this.mWord = word;
+ }
+ }
+
+ private static boolean isSeparator(int code, String sep) {
+ return sep.indexOf(code) != -1;
+ }
+
+ // Get the word before the whitespace preceding the non-whitespace preceding the cursor.
+ // Also, it won't return words that end in a separator.
+ // Example :
+ // "abc def|" -> abc
+ // "abc def |" -> abc
+ // "abc def. |" -> abc
+ // "abc def . |" -> def
+ // "abc|" -> null
+ // "abc |" -> null
+ // "abc. def|" -> null
+ public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) {
+ if (prev == null) return null;
+ String[] w = spaceRegex.split(prev);
+
+ // If we can't find two words, or we found an empty word, return null.
+ if (w.length < 2 || w[w.length - 2].length() <= 0) return null;
+
+ // If ends in a separator, return null
+ char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1);
+ if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
+
+ return w[w.length - 2];
+ }
+
+ public CharSequence getThisWord(String sentenceSeperators) {
+ if (null == mIC) return null;
+ final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
+ return getThisWord(prev, sentenceSeperators);
+ }
+
+ // Get the word immediately before the cursor, even if there is whitespace between it and
+ // the cursor - but not if there is punctuation.
+ // Example :
+ // "abc def|" -> def
+ // "abc def |" -> def
+ // "abc def. |" -> null
+ // "abc def . |" -> null
+ public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) {
+ if (prev == null) return null;
+ String[] w = spaceRegex.split(prev);
+
+ // No word : return null
+ if (w.length < 1 || w[w.length - 1].length() <= 0) return null;
+
+ // If ends in a separator, return null
+ char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1);
+ if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
+
+ return w[w.length - 1];
+ }
+
+ /**
+ * @param separators characters which may separate words
+ * @return the word that surrounds the cursor, including up to one trailing
+ * separator. For example, if the field contains "he|llo world", where |
+ * represents the cursor, then "hello " will be returned.
+ */
+ public String getWordAtCursor(String separators) {
+ // getWordRangeAtCursor returns null if the connection is null
+ Range r = getWordRangeAtCursor(separators, 0);
+ return (r == null) ? null : r.mWord;
+ }
+
+ private int getCursorPosition() {
+ if (null == mIC) return INVALID_CURSOR_POSITION;
+ final ExtractedText extracted = mIC.getExtractedText(new ExtractedTextRequest(), 0);
+ if (extracted == null) {
+ return INVALID_CURSOR_POSITION;
+ }
+ return extracted.startOffset + extracted.selectionStart;
+ }
+
+ /**
+ * Returns the text surrounding the cursor.
+ *
+ * @param sep a string of characters that split words.
+ * @param additionalPrecedingWordsCount the number of words before the current word that should
+ * be included in the returned range
+ * @return a range containing the text surrounding the cursor
+ */
+ public Range getWordRangeAtCursor(String sep, int additionalPrecedingWordsCount) {
+ if (mIC == null || sep == null) {
+ return null;
+ }
+ CharSequence before = mIC.getTextBeforeCursor(1000, 0);
+ CharSequence after = mIC.getTextAfterCursor(1000, 0);
+ if (before == null || after == null) {
+ return null;
+ }
+
+ // Going backward, alternate skipping non-separators and separators until enough words
+ // have been read.
+ int start = before.length();
+ boolean isStoppingAtWhitespace = true; // toggles to indicate what to stop at
+ while (true) { // see comments below for why this is guaranteed to halt
+ while (start > 0) {
+ final int codePoint = Character.codePointBefore(before, start);
+ if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) {
+ break; // inner loop
+ }
+ --start;
+ if (Character.isSupplementaryCodePoint(codePoint)) {
+ --start;
+ }
+ }
+ // isStoppingAtWhitespace is true every other time through the loop,
+ // so additionalPrecedingWordsCount is guaranteed to become < 0, which
+ // guarantees outer loop termination
+ if (isStoppingAtWhitespace && (--additionalPrecedingWordsCount < 0)) {
+ break; // outer loop
+ }
+ isStoppingAtWhitespace = !isStoppingAtWhitespace;
+ }
+
+ // Find last word separator after the cursor
+ int end = -1;
+ while (++end < after.length()) {
+ final int codePoint = Character.codePointAt(after, end);
+ if (isSeparator(codePoint, sep)) {
+ break;
+ }
+ if (Character.isSupplementaryCodePoint(codePoint)) {
+ ++end;
+ }
+ }
+
+ int cursor = getCursorPosition();
+ if (start >= 0 && cursor + end <= after.length() + before.length()) {
+ String word = before.toString().substring(start, before.length())
+ + after.toString().substring(0, end);
+ return new Range(before.length() - start, end, word);
+ }
+
+ return null;
+ }
+
+ public boolean isCursorTouchingWord(final SettingsValues settingsValues) {
+ CharSequence before = getTextBeforeCursor(1, 0);
+ CharSequence after = getTextAfterCursor(1, 0);
+ if (!TextUtils.isEmpty(before) && !settingsValues.isWordSeparator(before.charAt(0))
+ && !settingsValues.isSymbolExcludedFromWordSeparators(before.charAt(0))) {
+ return true;
+ }
+ if (!TextUtils.isEmpty(after) && !settingsValues.isWordSeparator(after.charAt(0))
+ && !settingsValues.isSymbolExcludedFromWordSeparators(after.charAt(0))) {
+ return true;
+ }
+ return false;
+ }
+
+ public void removeTrailingSpace() {
+ checkBatchEdit();
+ final CharSequence lastOne = getTextBeforeCursor(1, 0);
+ if (lastOne != null && lastOne.length() == 1
+ && lastOne.charAt(0) == Keyboard.CODE_SPACE) {
+ deleteSurroundingText(1, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(1);
+ }
+ }
+ }
+
+ public boolean sameAsTextBeforeCursor(final CharSequence text) {
+ final CharSequence beforeText = getTextBeforeCursor(text.length(), 0);
+ return TextUtils.equals(text, beforeText);
+ }
+
+ /* (non-javadoc)
+ * Returns the word before the cursor if the cursor is at the end of a word, null otherwise
+ */
+ public CharSequence getWordBeforeCursorIfAtEndOfWord(final SettingsValues settings) {
+ // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
+ // separator or end of line/text)
+ // Example: "test|"<EOL> "te|st" get rejected here
+ final CharSequence textAfterCursor = getTextAfterCursor(1, 0);
+ if (!TextUtils.isEmpty(textAfterCursor)
+ && !settings.isWordSeparator(textAfterCursor.charAt(0))) return null;
+
+ // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe)
+ // Example: " -|" gets rejected here but "e-|" and "e|" are okay
+ CharSequence word = getWordAtCursor(settings.mWordSeparators);
+ // We don't suggest on leading single quotes, so we have to remove them from the word if
+ // it starts with single quotes.
+ while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) {
+ word = word.subSequence(1, word.length());
+ }
+ if (TextUtils.isEmpty(word)) return null;
+ // Find the last code point of the string
+ final int lastCodePoint = Character.codePointBefore(word, word.length());
+ // If for some reason the text field contains non-unicode binary data, or if the
+ // charsequence is exactly one char long and the contents is a low surrogate, return null.
+ if (!Character.isDefined(lastCodePoint)) return null;
+ // Bail out if the cursor is not at the end of a word (cursor must be preceded by
+ // non-whitespace, non-separator, non-start-of-text)
+ // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
+ if (settings.isWordSeparator(lastCodePoint)) return null;
+ final char firstChar = word.charAt(0); // we just tested that word is not empty
+ if (word.length() == 1 && !Character.isLetter(firstChar)) return null;
+
+ // We only suggest on words that start with a letter or a symbol that is excluded from
+ // word separators (see #handleCharacterWhileInBatchEdit).
+ if (!(Character.isLetter(firstChar)
+ || settings.isSymbolExcludedFromWordSeparators(firstChar))) {
+ return null;
+ }
+
+ return word;
+ }
+
+ public boolean revertDoubleSpace() {
+ checkBatchEdit();
+ // Here we test whether we indeed have a period and a space before us. This should not
+ // be needed, but it's there just in case something went wrong.
+ final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
+ if (!". ".equals(textBeforeCursor)) {
+ // Theoretically we should not be coming here if there isn't ". " before the
+ // cursor, but the application may be changing the text while we are typing, so
+ // anything goes. We should not crash.
+ Log.d(TAG, "Tried to revert double-space combo but we didn't find "
+ + "\". \" just before the cursor.");
+ return false;
+ }
+ deleteSurroundingText(2, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(2);
+ }
+ commitText(" ", 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_revertDoubleSpaceWhileInBatchEdit();
+ }
+ return true;
+ }
+
+ public boolean revertSwapPunctuation() {
+ checkBatchEdit();
+ // Here we test whether we indeed have a space and something else before us. This should not
+ // be needed, but it's there just in case something went wrong.
+ final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
+ // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
+ // enter surrogate pairs this code will have been removed.
+ if (TextUtils.isEmpty(textBeforeCursor)
+ || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) {
+ // We may only come here if the application is changing the text while we are typing.
+ // This is quite a broken case, but not logically impossible, so we shouldn't crash,
+ // but some debugging log may be in order.
+ Log.d(TAG, "Tried to revert a swap of punctuation but we didn't "
+ + "find a space just before the cursor.");
+ return false;
+ }
+ deleteSurroundingText(2, 0);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_deleteSurroundingText(2);
+ }
+ commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
+ if (ProductionFlag.IS_EXPERIMENTAL) {
+ ResearchLogger.latinIME_revertSwapPunctuation();
+ }
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 152d66851..4c89a6e91 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -69,9 +69,7 @@ public class Settings extends InputMethodSettingsFragment
public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
"pref_key_preview_popup_dismiss_delay";
public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
- public static final String PREF_BIGRAM_SUGGESTION = "next_word_suggestion";
public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
- public static final String PREF_KEY_ENABLE_SPAN_INSERT = "enable_span_insert";
public static final String PREF_VIBRATION_DURATION_SETTINGS =
"pref_vibration_duration_settings";
public static final String PREF_KEYPRESS_SOUND_VOLUME =
@@ -87,9 +85,7 @@ public class Settings extends InputMethodSettingsFragment
private ListPreference mShowCorrectionSuggestionsPreference;
private ListPreference mAutoCorrectionThresholdPreference;
private ListPreference mKeyPreviewPopupDismissDelay;
- // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary
- private CheckBoxPreference mBigramSuggestion;
- // Prediction: use bigrams to predict the next word when there is no input for it yet
+ // Use bigrams to predict the next word when there is no input for it yet
private CheckBoxPreference mBigramPrediction;
private Preference mDebugSettingsPreference;
@@ -100,7 +96,6 @@ public class Settings extends InputMethodSettingsFragment
final String autoCorrectionOff = getResources().getString(
R.string.auto_correction_threshold_mode_index_off);
final String currentSetting = mAutoCorrectionThresholdPreference.getValue();
- mBigramSuggestion.setEnabled(!currentSetting.equals(autoCorrectionOff));
if (null != mBigramPrediction) {
mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff));
}
@@ -124,7 +119,6 @@ public class Settings extends InputMethodSettingsFragment
mAutoCorrectionThresholdPreference =
(ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD);
- mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTION);
mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS);
mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS);
if (mDebugSettingsPreference != null) {
@@ -151,9 +145,6 @@ public class Settings extends InputMethodSettingsFragment
final PreferenceGroup advancedSettings =
(PreferenceGroup) findPreference(PREF_ADVANCED_SETTINGS);
- // Remove those meaningless options for now. TODO: delete them for good
- advancedSettings.removePreference(findPreference(PREF_BIGRAM_SUGGESTION));
- advancedSettings.removePreference(findPreference(PREF_KEY_ENABLE_SPAN_INSERT));
if (!VibratorUtils.getInstance(context).hasVibrator()) {
generalSettings.removePreference(findPreference(PREF_VIBRATE_ON));
if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
@@ -161,19 +152,30 @@ public class Settings extends InputMethodSettingsFragment
}
}
- final boolean showPopupOption = res.getBoolean(
+ final boolean showKeyPreviewPopupOption = res.getBoolean(
R.bool.config_enable_show_popup_on_keypress_option);
- if (!showPopupOption) {
+ mKeyPreviewPopupDismissDelay =
+ (ListPreference) findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
+ if (!showKeyPreviewPopupOption) {
generalSettings.removePreference(findPreference(PREF_POPUP_ON));
- }
-
- final boolean showBigramSuggestionsOption = res.getBoolean(
- R.bool.config_enable_next_word_suggestions_option);
- if (!showBigramSuggestionsOption) {
- textCorrectionGroup.removePreference(mBigramSuggestion);
- if (null != mBigramPrediction) {
- textCorrectionGroup.removePreference(mBigramPrediction);
+ if (null != advancedSettings) { // Theoretically advancedSettings cannot be null
+ advancedSettings.removePreference(mKeyPreviewPopupDismissDelay);
+ }
+ } else {
+ final String[] entries = new String[] {
+ res.getString(R.string.key_preview_popup_dismiss_no_delay),
+ res.getString(R.string.key_preview_popup_dismiss_default_delay),
+ };
+ final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
+ R.integer.config_key_preview_linger_timeout));
+ mKeyPreviewPopupDismissDelay.setEntries(entries);
+ mKeyPreviewPopupDismissDelay.setEntryValues(
+ new String[] { "0", popupDismissDelayDefaultValue });
+ if (null == mKeyPreviewPopupDismissDelay.getValue()) {
+ mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
}
+ mKeyPreviewPopupDismissDelay.setEnabled(
+ SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
}
final CheckBoxPreference includeOtherImesInLanguageSwitchList =
@@ -181,23 +183,6 @@ public class Settings extends InputMethodSettingsFragment
includeOtherImesInLanguageSwitchList.setEnabled(
!SettingsValues.isLanguageSwitchKeySupressed(prefs));
- mKeyPreviewPopupDismissDelay =
- (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
- final String[] entries = new String[] {
- res.getString(R.string.key_preview_popup_dismiss_no_delay),
- res.getString(R.string.key_preview_popup_dismiss_default_delay),
- };
- final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
- R.integer.config_key_preview_linger_timeout));
- mKeyPreviewPopupDismissDelay.setEntries(entries);
- mKeyPreviewPopupDismissDelay.setEntryValues(
- new String[] { "0", popupDismissDelayDefaultValue });
- if (null == mKeyPreviewPopupDismissDelay.getValue()) {
- mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
- }
- mKeyPreviewPopupDismissDelay.setEnabled(
- SettingsValues.isKeyPreviewPopupEnabled(prefs, res));
-
final PreferenceScreen dictionaryLink =
(PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
final Intent intent = dictionaryLink.getIntent();
@@ -323,13 +308,15 @@ public class Settings extends InputMethodSettingsFragment
private void updateKeyPreviewPopupDelaySummary() {
final ListPreference lp = mKeyPreviewPopupDismissDelay;
- lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]);
+ final CharSequence[] entries = lp.getEntries();
+ if (entries == null || entries.length <= 0) return;
+ lp.setSummary(entries[lp.findIndexOfValue(lp.getValue())]);
}
private void updateVoiceModeSummary() {
mVoicePreference.setSummary(
getResources().getStringArray(R.array.voice_input_modes_summary)
- [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
+ [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]);
}
private void refreshEnablingsOfKeypressSoundAndVibrationSettings(
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index b07c3e59f..aab84fccd 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
@@ -29,7 +30,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.Map;
/**
* When you call the constructor of this class, you may want to change the current system locale by
@@ -38,6 +38,19 @@ import java.util.Map;
public class SettingsValues {
private static final String TAG = SettingsValues.class.getSimpleName();
+ private static final int SUGGESTION_VISIBILITY_SHOW_VALUE
+ = R.string.prefs_suggestion_visibility_show_value;
+ private static final int SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE
+ = R.string.prefs_suggestion_visibility_show_only_portrait_value;
+ private static final int SUGGESTION_VISIBILITY_HIDE_VALUE
+ = R.string.prefs_suggestion_visibility_hide_value;
+
+ private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] {
+ SUGGESTION_VISIBILITY_SHOW_VALUE,
+ SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE,
+ SUGGESTION_VISIBILITY_HIDE_VALUE
+ };
+
// From resources:
public final int mDelayUpdateOldSuggestions;
public final String mWeakSpaceStrippers;
@@ -63,27 +76,30 @@ public class SettingsValues {
@SuppressWarnings("unused") // TODO: Use this
private final String mKeyPreviewPopupDismissDelayRawValue;
public final boolean mUseContactsDict;
- // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary
- public final boolean mBigramSuggestionEnabled;
- // Prediction: use bigrams to predict the next word when there is no input for it yet
+ // Use bigrams to predict the next word when there is no input for it yet
public final boolean mBigramPredictionEnabled;
- public final boolean mEnableSuggestionSpanInsertion;
@SuppressWarnings("unused") // TODO: Use this
private final int mVibrationDurationSettingsRawValue;
@SuppressWarnings("unused") // TODO: Use this
private final float mKeypressSoundVolumeRawValue;
private final InputMethodSubtype[] mAdditionalSubtypes;
+ // From the input box
+ private final InputAttributes mInputAttributes;
+
// Deduced settings
public final int mKeypressVibrationDuration;
public final float mFxVolume;
public final int mKeyPreviewPopupDismissDelay;
- public final boolean mAutoCorrectEnabled;
+ private final boolean mAutoCorrectEnabled;
public final float mAutoCorrectionThreshold;
+ public final boolean mCorrectionEnabled;
+ public final int mSuggestionVisibility;
private final boolean mVoiceKeyEnabled;
private final boolean mVoiceKeyOnMain;
- public SettingsValues(final SharedPreferences prefs, final Context context) {
+ public SettingsValues(final SharedPreferences prefs, final InputAttributes inputAttributes,
+ final Context context) {
final Resources res = context.getResources();
// Get the resources
@@ -109,6 +125,13 @@ public class SettingsValues {
mSymbolsExcludedFromWordSeparators, res);
mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
+ // Store the input attributes
+ if (null == inputAttributes) {
+ mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
+ } else {
+ mInputAttributes = inputAttributes;
+ }
+
// Get the settings preferences
mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
mVibrateOn = isVibrateOn(context, prefs, res);
@@ -131,12 +154,7 @@ public class SettingsValues {
Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout)));
mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue);
- mBigramSuggestionEnabled = mAutoCorrectEnabled
- && isBigramSuggestionEnabled(prefs, res, mAutoCorrectEnabled);
- mBigramPredictionEnabled = mBigramSuggestionEnabled
- && isBigramPredictionEnabled(prefs, res);
- // TODO: remove mEnableSuggestionSpanInsertion. It's always true.
- mEnableSuggestionSpanInsertion = true;
+ mBigramPredictionEnabled = isBigramPredictionEnabled(prefs, res);
mVibrationDurationSettingsRawValue =
prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
mKeypressSoundVolumeRawValue = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
@@ -151,22 +169,23 @@ public class SettingsValues {
mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain);
mAdditionalSubtypes = AdditionalSubtype.createAdditionalSubtypesArray(
getPrefAdditionalSubtypes(prefs, res));
+ mCorrectionEnabled = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect;
+ mSuggestionVisibility = createSuggestionVisibility(res);
}
// Helper functions to create member values.
private static SuggestedWords createSuggestPuncList(final String[] puncs) {
- final ArrayList<SuggestedWords.SuggestedWordInfo> puncList =
- new ArrayList<SuggestedWords.SuggestedWordInfo>();
+ final ArrayList<SuggestedWordInfo> puncList = new ArrayList<SuggestedWordInfo>();
if (puncs != null) {
for (final String puncSpec : puncs) {
- puncList.add(new SuggestedWords.SuggestedWordInfo(
- KeySpecParser.getLabel(puncSpec), SuggestedWordInfo.MAX_SCORE));
+ puncList.add(new SuggestedWordInfo(KeySpecParser.getLabel(puncSpec),
+ SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED,
+ Dictionary.TYPE_HARDCODED));
}
}
return new SuggestedWords(puncList,
false /* typedWordValid */,
false /* hasAutoCorrectionCandidate */,
- false /* allowsToBeAutoCorrected */,
true /* isPunctuationSuggestions */,
false /* isObsoleteSuggestions */,
false /* isPrediction */);
@@ -184,6 +203,16 @@ public class SettingsValues {
return wordSeparators;
}
+ private int createSuggestionVisibility(final Resources res) {
+ final String suggestionVisiblityStr = mShowSuggestionsSetting;
+ for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) {
+ if (suggestionVisiblityStr.equals(res.getString(visibility))) {
+ return visibility;
+ }
+ }
+ throw new RuntimeException("Bug: visibility string is not configured correctly");
+ }
+
private static boolean isVibrateOn(final Context context, final SharedPreferences prefs,
final Resources res) {
final boolean hasVibrator = VibratorUtils.getInstance(context).hasVibrator();
@@ -191,6 +220,26 @@ public class SettingsValues {
res.getBoolean(R.bool.config_default_vibration_enabled));
}
+ public boolean isApplicationSpecifiedCompletionsOn() {
+ return mInputAttributes.mApplicationSpecifiedCompletionOn;
+ }
+
+ public boolean isEditorActionNext() {
+ return mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT;
+ }
+
+ public boolean isSuggestionsRequested(final int displayOrientation) {
+ return mInputAttributes.mIsSettingsSuggestionStripOn
+ && (mCorrectionEnabled
+ || isSuggestionStripVisibleInOrientation(displayOrientation));
+ }
+
+ public boolean isSuggestionStripVisibleInOrientation(final int orientation) {
+ return (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_VALUE)
+ || (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE
+ && orientation == Configuration.ORIENTATION_PORTRAIT);
+ }
+
public boolean isWordSeparator(int code) {
return mWordSeparators.contains(String.valueOf((char)code));
}
@@ -240,12 +289,6 @@ public class SettingsValues {
R.integer.config_key_preview_linger_timeout))));
}
- private static boolean isBigramSuggestionEnabled(final SharedPreferences sp,
- final Resources resources, final boolean autoCorrectEnabled) {
- // TODO: remove this method. Bigram suggestion is always true.
- return true;
- }
-
private static boolean isBigramPredictionEnabled(final SharedPreferences sp,
final Resources resources) {
return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean(
@@ -367,4 +410,9 @@ public class SettingsValues {
final String newStr = Utils.localeAndTimeHashMapToStr(map);
prefs.edit().putString(Settings.PREF_LAST_USER_DICTIONARY_WRITE_TIME, newStr).apply();
}
+
+ // For debug.
+ public String getInputAttributesDebugString() {
+ return mInputAttributes.toString();
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index a43b90525..6e7d985d6 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -184,6 +184,9 @@ public class StringUtils {
final char[] characters = string.toCharArray();
final int length = characters.length;
final int[] codePoints = new int[Character.codePointCount(characters, 0, length)];
+ if (length <= 0) {
+ return new int[0];
+ }
int codePoint = Character.codePointAt(characters, 0);
int dsti = 0;
for (int srci = Character.charCount(codePoint);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 336a76f4b..70751c107 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -26,6 +26,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import java.io.File;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
@@ -34,79 +35,49 @@ import java.util.concurrent.ConcurrentHashMap;
* This class loads a dictionary and provides a list of suggestions for a given sequence of
* characters. This includes corrections and completions.
*/
-public class Suggest implements Dictionary.WordCallback {
+public class Suggest {
public static final String TAG = Suggest.class.getSimpleName();
- public static final int APPROX_MAX_WORD_LENGTH = 32;
-
+ // TODO: rename this to CORRECTION_OFF
public static final int CORRECTION_NONE = 0;
+ // TODO: rename this to CORRECTION_ON
public static final int CORRECTION_FULL = 1;
- public static final int CORRECTION_FULL_BIGRAM = 2;
-
- // It seems the following values are only used for logging.
- public static final int DIC_USER_TYPED = 0;
- public static final int DIC_MAIN = 1;
- public static final int DIC_USER = 2;
- public static final int DIC_USER_HISTORY = 3;
- public static final int DIC_CONTACTS = 4;
- public static final int DIC_WHITELIST = 6;
- // If you add a type of dictionary, increment DIC_TYPE_LAST_ID
- // TODO: this value seems unused. Remove it?
- public static final int DIC_TYPE_LAST_ID = 6;
- public static final String DICT_KEY_MAIN = "main";
- public static final String DICT_KEY_CONTACTS = "contacts";
- // User dictionary, the system-managed one.
- public static final String DICT_KEY_USER = "user";
- // User history dictionary for the unigram map, internal to LatinIME
- public static final String DICT_KEY_USER_HISTORY_UNIGRAM = "history_unigram";
- // User history dictionary for the bigram map, internal to LatinIME
- public static final String DICT_KEY_USER_HISTORY_BIGRAM = "history_bigram";
- public static final String DICT_KEY_WHITELIST ="whitelist";
private static final boolean DBG = LatinImeLogger.sDBG;
- private boolean mHasMainDictionary;
- private Dictionary mContactsDict;
+ private Dictionary mMainDictionary;
+ private ContactsBinaryDictionary mContactsDict;
private WhitelistDictionary mWhiteListDictionary;
- private final ConcurrentHashMap<String, Dictionary> mUnigramDictionaries =
- new ConcurrentHashMap<String, Dictionary>();
- private final ConcurrentHashMap<String, Dictionary> mBigramDictionaries =
+ private final ConcurrentHashMap<String, Dictionary> mDictionaries =
new ConcurrentHashMap<String, Dictionary>();
- private int mPrefMaxSuggestions = 18;
-
- private static final int PREF_MAX_BIGRAMS = 60;
+ public static final int MAX_SUGGESTIONS = 18;
private float mAutoCorrectionThreshold;
- private ArrayList<SuggestedWordInfo> mSuggestions = new ArrayList<SuggestedWordInfo>();
- private ArrayList<SuggestedWordInfo> mBigramSuggestions = new ArrayList<SuggestedWordInfo>();
- private CharSequence mConsideredWord;
-
- // TODO: Remove these member variables by passing more context to addWord() callback method
- private boolean mIsFirstCharCapitalized;
- private boolean mIsAllUpperCase;
- private int mTrailingSingleQuotesCount;
+ // Locale used for upper- and title-casing words
+ final private Locale mLocale;
private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
public Suggest(final Context context, final Locale locale) {
initAsynchronously(context, locale);
+ mLocale = locale;
}
/* package for test */ Suggest(final Context context, final File dictionary,
final long startOffset, final long length, final Locale locale) {
final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(context, dictionary,
startOffset, length /* useFullEditDistance */, false, locale);
- mHasMainDictionary = null != mainDict;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict);
+ mLocale = locale;
+ mMainDictionary = mainDict;
+ addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, mainDict);
initWhitelistAndAutocorrectAndPool(context, locale);
}
private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) {
mWhiteListDictionary = new WhitelistDictionary(context, locale);
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary);
+ addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_WHITELIST, mWhiteListDictionary);
}
private void initAsynchronously(final Context context, final Locale locale) {
@@ -129,15 +100,14 @@ public class Suggest implements Dictionary.WordCallback {
}
public void resetMainDict(final Context context, final Locale locale) {
- mHasMainDictionary = false;
+ mMainDictionary = null;
new Thread("InitializeBinaryDictionary") {
@Override
public void run() {
final DictionaryCollection newMainDict =
DictionaryFactory.createMainDictionaryFromManager(context, locale);
- mHasMainDictionary = null != newMainDict && !newMainDict.isEmpty();
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict);
+ addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_MAIN, newMainDict);
+ mMainDictionary = newMainDict;
}
}.start();
}
@@ -145,27 +115,27 @@ public class Suggest implements Dictionary.WordCallback {
// The main dictionary could have been loaded asynchronously. Don't cache the return value
// of this method.
public boolean hasMainDictionary() {
- return mHasMainDictionary;
+ return null != mMainDictionary && mMainDictionary.isInitialized();
}
- public Dictionary getContactsDictionary() {
- return mContactsDict;
+ public Dictionary getMainDictionary() {
+ return mMainDictionary;
}
- public ConcurrentHashMap<String, Dictionary> getUnigramDictionaries() {
- return mUnigramDictionaries;
+ public ContactsBinaryDictionary getContactsDictionary() {
+ return mContactsDict;
}
- public static int getApproxMaxWordLength() {
- return APPROX_MAX_WORD_LENGTH;
+ public ConcurrentHashMap<String, Dictionary> getUnigramDictionaries() {
+ return mDictionaries;
}
/**
* Sets an optional user dictionary resource to be loaded. The user dictionary is consulted
* before the main dictionary, if set. This refers to the system-managed user dictionary.
*/
- public void setUserDictionary(Dictionary userDictionary) {
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER, userDictionary);
+ public void setUserDictionary(UserBinaryDictionary userDictionary) {
+ addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER, userDictionary);
}
/**
@@ -173,184 +143,137 @@ public class Suggest implements Dictionary.WordCallback {
* the contacts dictionary by passing null to this method. In this case no contacts dictionary
* won't be used.
*/
- public void setContactsDictionary(Dictionary contactsDictionary) {
+ public void setContactsDictionary(ContactsBinaryDictionary contactsDictionary) {
mContactsDict = contactsDictionary;
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary);
+ addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_CONTACTS, contactsDictionary);
}
- public void setUserHistoryDictionary(Dictionary userHistoryDictionary) {
- addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER_HISTORY_UNIGRAM,
- userHistoryDictionary);
- addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_HISTORY_BIGRAM,
- userHistoryDictionary);
+ public void setUserHistoryDictionary(UserHistoryDictionary userHistoryDictionary) {
+ addOrReplaceDictionary(mDictionaries, Dictionary.TYPE_USER_HISTORY, userHistoryDictionary);
}
public void setAutoCorrectionThreshold(float threshold) {
mAutoCorrectionThreshold = threshold;
}
- private static CharSequence capitalizeWord(final boolean all, final boolean first,
- final CharSequence word) {
- if (TextUtils.isEmpty(word) || !(all || first)) return word;
- final int wordLength = word.length();
- final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
- // TODO: Must pay attention to locale when changing case.
- if (all) {
- sb.append(word.toString().toUpperCase());
- } else if (first) {
- sb.append(Character.toUpperCase(word.charAt(0)));
- if (wordLength > 1) {
- sb.append(word.subSequence(1, wordLength));
- }
- }
- return sb;
- }
-
- protected void addBigramToSuggestions(SuggestedWordInfo bigram) {
- mSuggestions.add(bigram);
- }
-
- private static final WordComposer sEmptyWordComposer = new WordComposer();
- public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) {
- LatinImeLogger.onStartSuggestion(prevWordForBigram);
- mIsFirstCharCapitalized = false;
- mIsAllUpperCase = false;
- mTrailingSingleQuotesCount = 0;
- mSuggestions = new ArrayList<SuggestedWordInfo>(mPrefMaxSuggestions);
-
- // Treating USER_TYPED as UNIGRAM suggestion for logging now.
- LatinImeLogger.onAddSuggestedWord("", Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
- mConsideredWord = "";
-
- mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
-
- getAllBigrams(prevWordForBigram, sEmptyWordComposer);
-
- // Nothing entered: return all bigrams for the previous word
- int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions);
- for (int i = 0; i < insertCount; ++i) {
- addBigramToSuggestions(mBigramSuggestions.get(i));
- }
-
- SuggestedWordInfo.removeDups(mSuggestions);
-
- return new SuggestedWords(mSuggestions,
- false /* typedWordValid */,
- false /* hasAutoCorrectionCandidate */,
- false /* allowsToBeAutoCorrected */,
- false /* isPunctuationSuggestions */,
- false /* isObsoleteSuggestions */,
- true /* isPrediction */);
- }
-
// TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
public SuggestedWords getSuggestedWords(
final WordComposer wordComposer, CharSequence prevWordForBigram,
- final ProximityInfo proximityInfo, final int correctionMode) {
+ final ProximityInfo proximityInfo, final boolean isCorrectionEnabled,
+ // TODO: remove isPrediction parameter. It effectively means the same thing
+ // as wordComposer.size() <= 1
+ final boolean isPrediction) {
LatinImeLogger.onStartSuggestion(prevWordForBigram);
- mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
- mIsAllUpperCase = wordComposer.isAllUpperCase();
- mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
- mSuggestions = new ArrayList<SuggestedWordInfo>(mPrefMaxSuggestions);
+ final boolean isFirstCharCapitalized =
+ !isPrediction && wordComposer.isFirstCharCapitalized();
+ final boolean isAllUpperCase = !isPrediction && wordComposer.isAllUpperCase();
+ final int trailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
+ final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator,
+ MAX_SUGGESTIONS);
final String typedWord = wordComposer.getTypedWord();
- final String consideredWord = mTrailingSingleQuotesCount > 0
- ? typedWord.substring(0, typedWord.length() - mTrailingSingleQuotesCount)
+ final String consideredWord = trailingSingleQuotesCount > 0
+ ? typedWord.substring(0, typedWord.length() - trailingSingleQuotesCount)
: typedWord;
- // Treating USER_TYPED as UNIGRAM suggestion for logging now.
- LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM);
- mConsideredWord = consideredWord;
+ LatinImeLogger.onAddSuggestedWord(typedWord, Dictionary.TYPE_USER_TYPED);
- if (wordComposer.size() <= 1 && (correctionMode == CORRECTION_FULL_BIGRAM)) {
+ if (wordComposer.size() <= 1 && isCorrectionEnabled) {
// At first character typed, search only the bigrams
- mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
-
if (!TextUtils.isEmpty(prevWordForBigram)) {
- getAllBigrams(prevWordForBigram, wordComposer);
- if (TextUtils.isEmpty(consideredWord)) {
- // Nothing entered: return all bigrams for the previous word
- int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions);
- for (int i = 0; i < insertCount; ++i) {
- addBigramToSuggestions(mBigramSuggestions.get(i));
- }
- } else {
- // Word entered: return only bigrams that match the first char of the typed word
- final char currentChar = consideredWord.charAt(0);
+ final CharSequence lowerPrevWord;
+ if (StringUtils.hasUpperCase(prevWordForBigram)) {
// TODO: Must pay attention to locale when changing case.
- // TODO: Use codepoint instead of char
- final char currentCharUpper = Character.toUpperCase(currentChar);
- int count = 0;
- final int bigramSuggestionSize = mBigramSuggestions.size();
- for (int i = 0; i < bigramSuggestionSize; i++) {
- final SuggestedWordInfo bigramSuggestion = mBigramSuggestions.get(i);
- final char bigramSuggestionFirstChar =
- (char)bigramSuggestion.codePointAt(0);
- if (bigramSuggestionFirstChar == currentChar
- || bigramSuggestionFirstChar == currentCharUpper) {
- addBigramToSuggestions(bigramSuggestion);
- if (++count > mPrefMaxSuggestions) break;
- }
+ lowerPrevWord = prevWordForBigram.toString().toLowerCase();
+ } else {
+ lowerPrevWord = null;
+ }
+ for (final String key : mDictionaries.keySet()) {
+ final Dictionary dictionary = mDictionaries.get(key);
+ suggestionsSet.addAll(dictionary.getBigrams(wordComposer, prevWordForBigram));
+ if (null != lowerPrevWord) {
+ suggestionsSet.addAll(dictionary.getBigrams(wordComposer, lowerPrevWord));
}
}
}
-
} else if (wordComposer.size() > 1) {
final WordComposer wordComposerForLookup;
- if (mTrailingSingleQuotesCount > 0) {
+ if (trailingSingleQuotesCount > 0) {
wordComposerForLookup = new WordComposer(wordComposer);
- for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) {
wordComposerForLookup.deleteLast();
}
} else {
wordComposerForLookup = wordComposer;
}
// At second character typed, search the unigrams (scores being affected by bigrams)
- for (final String key : mUnigramDictionaries.keySet()) {
+ for (final String key : mDictionaries.keySet()) {
// Skip UserUnigramDictionary and WhitelistDictionary to lookup
- if (key.equals(DICT_KEY_USER_HISTORY_UNIGRAM) || key.equals(DICT_KEY_WHITELIST))
+ if (key.equals(Dictionary.TYPE_USER_HISTORY)
+ || key.equals(Dictionary.TYPE_WHITELIST))
continue;
- final Dictionary dictionary = mUnigramDictionaries.get(key);
- dictionary.getWords(wordComposerForLookup, prevWordForBigram, this, proximityInfo);
+ final Dictionary dictionary = mDictionaries.get(key);
+ suggestionsSet.addAll(dictionary.getWords(
+ wordComposerForLookup, prevWordForBigram, proximityInfo));
}
}
- final CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase,
- mIsFirstCharCapitalized, mWhiteListDictionary.getWhitelistedWord(consideredWord));
+ final CharSequence whitelistedWord =
+ mWhiteListDictionary.getWhitelistedWord(consideredWord);
final boolean hasAutoCorrection;
- if (CORRECTION_FULL == correctionMode || CORRECTION_FULL_BIGRAM == correctionMode) {
- final CharSequence autoCorrection =
- AutoCorrection.computeAutoCorrectionWord(mUnigramDictionaries, wordComposer,
- mSuggestions, consideredWord, mAutoCorrectionThreshold,
- whitelistedWord);
- hasAutoCorrection = (null != autoCorrection);
+ if (!isCorrectionEnabled || wordComposer.isMostlyCaps() || wordComposer.isResumed()) {
+ hasAutoCorrection = false;
+ } else if (null != whitelistedWord) {
+ hasAutoCorrection = true;
+ } else if (!AutoCorrection.isWhitelistedOrNotAWord(
+ mDictionaries, consideredWord, wordComposer.isFirstCharCapitalized())) {
+ hasAutoCorrection = true;
+ } else if (suggestionsSet.isEmpty()) {
+ hasAutoCorrection = false;
+ } else if (AutoCorrection.suggestionExceedsAutoCorrectionThreshold(suggestionsSet.first(),
+ consideredWord, mAutoCorrectionThreshold)) {
+ hasAutoCorrection = !shouldBlockAutoCorrectionBySafetyNet(typedWord,
+ suggestionsSet.first().mWord);
} else {
hasAutoCorrection = false;
}
if (whitelistedWord != null) {
- if (mTrailingSingleQuotesCount > 0) {
- final StringBuilder sb = new StringBuilder(whitelistedWord);
- for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
- sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
- }
- mSuggestions.add(0, new SuggestedWordInfo(
- sb.toString(), SuggestedWordInfo.MAX_SCORE));
- } else {
- mSuggestions.add(0, new SuggestedWordInfo(
- whitelistedWord, SuggestedWordInfo.MAX_SCORE));
+ suggestionsSet.add(new SuggestedWordInfo(whitelistedWord,
+ SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_WHITELIST,
+ Dictionary.TYPE_WHITELIST));
+ }
+
+ final ArrayList<SuggestedWordInfo> suggestionsContainer =
+ new ArrayList<SuggestedWordInfo>(suggestionsSet);
+ final int suggestionsCount = suggestionsContainer.size();
+ if (isFirstCharCapitalized || isAllUpperCase || 0 != trailingSingleQuotesCount) {
+ for (int i = 0; i < suggestionsCount; ++i) {
+ final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+ final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
+ wordInfo, mLocale, isAllUpperCase, isFirstCharCapitalized,
+ trailingSingleQuotesCount);
+ suggestionsContainer.set(i, transformedWordInfo);
}
}
- mSuggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE));
- SuggestedWordInfo.removeDups(mSuggestions);
+ for (int i = 0; i < suggestionsCount; ++i) {
+ final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+ LatinImeLogger.onAddSuggestedWord(wordInfo.mWord.toString(), wordInfo.mSourceDict);
+ }
+
+ if (!TextUtils.isEmpty(typedWord)) {
+ suggestionsContainer.add(0, new SuggestedWordInfo(typedWord,
+ SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED,
+ Dictionary.TYPE_USER_TYPED));
+ }
+ SuggestedWordInfo.removeDups(suggestionsContainer);
final ArrayList<SuggestedWordInfo> suggestionsList;
- if (DBG) {
- suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, mSuggestions);
+ if (DBG && !suggestionsContainer.isEmpty()) {
+ suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, suggestionsContainer);
} else {
- suggestionsList = mSuggestions;
+ suggestionsList = suggestionsContainer;
}
// TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid"
@@ -358,51 +281,24 @@ public class Suggest implements Dictionary.WordCallback {
// The whitelist should be case-insensitive, so it's not possible to be consistent with
// a boolean flag. Right now this is handled with a slight hack in
// WhitelistDictionary#shouldForciblyAutoCorrectFrom.
- final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected(
+ final boolean allowsToBeAutoCorrected = AutoCorrection.isWhitelistedOrNotAWord(
getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized())
// If we don't have a main dictionary, we never want to auto-correct. The reason for this
// is, the user may have a contact whose name happens to match a valid word in their
// language, and it will unexpectedly auto-correct. For example, if the user types in
// English with no dictionary and has a "Will" in their contact list, "will" would
// always auto-correct to "Will" which is unwanted. Hence, no main dict => no auto-correct.
- && mHasMainDictionary;
+ && hasMainDictionary();
- boolean autoCorrectionAvailable = hasAutoCorrection;
- if (correctionMode == CORRECTION_FULL || correctionMode == CORRECTION_FULL_BIGRAM) {
- autoCorrectionAvailable |= !allowsToBeAutoCorrected;
- }
- // Don't auto-correct words with multiple capital letter
- autoCorrectionAvailable &= !wordComposer.isMostlyCaps();
- autoCorrectionAvailable &= !wordComposer.isResumed();
- if (allowsToBeAutoCorrected && suggestionsList.size() > 1 && mAutoCorrectionThreshold > 0
- && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord,
- suggestionsList.get(1).mWord)) {
- autoCorrectionAvailable = false;
- }
return new SuggestedWords(suggestionsList,
- !allowsToBeAutoCorrected /* typedWordValid */,
- autoCorrectionAvailable /* hasAutoCorrectionCandidate */,
- allowsToBeAutoCorrected /* allowsToBeAutoCorrected */,
+ // TODO: this first argument is lying. If this is a whitelisted word which is an
+ // actual word, it says typedWordValid = false, which looks wrong. We should either
+ // rename the attribute or change the value.
+ !isPrediction && !allowsToBeAutoCorrected /* typedWordValid */,
+ !isPrediction && hasAutoCorrection, /* hasAutoCorrectionCandidate */
false /* isPunctuationSuggestions */,
false /* isObsoleteSuggestions */,
- false /* isPrediction */);
- }
-
- /**
- * Adds all bigram predictions for prevWord. Also checks the lower case version of prevWord if
- * it contains any upper case characters.
- */
- private void getAllBigrams(final CharSequence prevWord, final WordComposer wordComposer) {
- if (StringUtils.hasUpperCase(prevWord)) {
- // TODO: Must pay attention to locale when changing case.
- final CharSequence lowerPrevWord = prevWord.toString().toLowerCase();
- for (final Dictionary dictionary : mBigramDictionaries.values()) {
- dictionary.getBigrams(wordComposer, lowerPrevWord, this);
- }
- }
- for (final Dictionary dictionary : mBigramDictionaries.values()) {
- dictionary.getBigrams(wordComposer, prevWord, this);
- }
+ isPrediction);
}
private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo(
@@ -431,87 +327,45 @@ public class Suggest implements Dictionary.WordCallback {
return suggestionsList;
}
- // TODO: Use codepoint instead of char
- @Override
- public boolean addWord(final char[] word, final int offset, final int length, int score,
- final int dicTypeId, final int dataType) {
- int dataTypeForLog = dataType;
- final ArrayList<SuggestedWordInfo> suggestions;
- final int prefMaxSuggestions;
- if (dataType == Dictionary.BIGRAM) {
- suggestions = mBigramSuggestions;
- prefMaxSuggestions = PREF_MAX_BIGRAMS;
- } else {
- suggestions = mSuggestions;
- prefMaxSuggestions = mPrefMaxSuggestions;
- }
-
- int pos = 0;
-
- // Check if it's the same word, only caps are different
- if (StringUtils.equalsIgnoreCase(mConsideredWord, word, offset, length)) {
- // TODO: remove this surrounding if clause and move this logic to
- // getSuggestedWordBuilder.
- if (suggestions.size() > 0) {
- final SuggestedWordInfo currentHighestWord = suggestions.get(0);
- // If the current highest word is also equal to typed word, we need to compare
- // frequency to determine the insertion position. This does not ensure strictly
- // correct ordering, but ensures the top score is on top which is enough for
- // removing duplicates correctly.
- if (StringUtils.equalsIgnoreCase(currentHighestWord.mWord, word, offset, length)
- && score <= currentHighestWord.mScore) {
- pos = 1;
- }
- }
- } else {
- // Check the last one's score and bail
- if (suggestions.size() >= prefMaxSuggestions
- && suggestions.get(prefMaxSuggestions - 1).mScore >= score) return true;
- while (pos < suggestions.size()) {
- final int curScore = suggestions.get(pos).mScore;
- if (curScore < score
- || (curScore == score && length < suggestions.get(pos).codePointCount())) {
- break;
- }
- pos++;
- }
- }
- if (pos >= prefMaxSuggestions) {
- return true;
+ private static class SuggestedWordInfoComparator implements Comparator<SuggestedWordInfo> {
+ // This comparator ranks the word info with the higher frequency first. That's because
+ // that's the order we want our elements in.
+ @Override
+ public int compare(final SuggestedWordInfo o1, final SuggestedWordInfo o2) {
+ if (o1.mScore > o2.mScore) return -1;
+ if (o1.mScore < o2.mScore) return 1;
+ if (o1.mCodePointCount < o2.mCodePointCount) return -1;
+ if (o1.mCodePointCount > o2.mCodePointCount) return 1;
+ return o1.mWord.toString().compareTo(o2.mWord.toString());
}
-
- final StringBuilder sb = new StringBuilder(getApproxMaxWordLength());
- // TODO: Must pay attention to locale when changing case.
- if (mIsAllUpperCase) {
- sb.append(new String(word, offset, length).toUpperCase());
- } else if (mIsFirstCharCapitalized) {
- sb.append(Character.toUpperCase(word[offset]));
- if (length > 1) {
- sb.append(word, offset + 1, length - 1);
- }
+ }
+ private static final SuggestedWordInfoComparator sSuggestedWordInfoComparator =
+ new SuggestedWordInfoComparator();
+
+ private static SuggestedWordInfo getTransformedSuggestedWordInfo(
+ final SuggestedWordInfo wordInfo, final Locale locale, final boolean isAllUpperCase,
+ final boolean isFirstCharCapitalized, final int trailingSingleQuotesCount) {
+ final StringBuilder sb = new StringBuilder(wordInfo.mWord.length());
+ if (isAllUpperCase) {
+ sb.append(wordInfo.mWord.toString().toUpperCase(locale));
+ } else if (isFirstCharCapitalized) {
+ sb.append(StringUtils.toTitleCase(wordInfo.mWord.toString(), locale));
} else {
- sb.append(word, offset, length);
+ sb.append(wordInfo.mWord);
}
- for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) {
+ for (int i = trailingSingleQuotesCount - 1; i >= 0; --i) {
sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE);
}
- suggestions.add(pos, new SuggestedWordInfo(sb, score));
- if (suggestions.size() > prefMaxSuggestions) {
- suggestions.remove(prefMaxSuggestions);
- } else {
- LatinImeLogger.onAddSuggestedWord(sb.toString(), dicTypeId, dataTypeForLog);
- }
- return true;
+ return new SuggestedWordInfo(sb, wordInfo.mScore, wordInfo.mKind, wordInfo.mSourceDict);
}
public void close() {
final HashSet<Dictionary> dictionaries = new HashSet<Dictionary>();
- dictionaries.addAll(mUnigramDictionaries.values());
- dictionaries.addAll(mBigramDictionaries.values());
+ dictionaries.addAll(mDictionaries.values());
for (final Dictionary dictionary : dictionaries) {
dictionary.close();
}
- mHasMainDictionary = false;
+ mMainDictionary = null;
}
// TODO: Resolve the inconsistencies between the native auto correction algorithms and
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 497fd3bfa..b84820cb8 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -25,12 +25,12 @@ import java.util.HashSet;
public class SuggestedWords {
public static final SuggestedWords EMPTY = new SuggestedWords(
- new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false, false);
+ new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false);
public final boolean mTypedWordValid;
public final boolean mHasAutoCorrectionCandidate;
+ public final boolean mWillAutoCorrect;
public final boolean mIsPunctuationSuggestions;
- public final boolean mAllowsToBeAutoCorrected;
public final boolean mIsObsoleteSuggestions;
public final boolean mIsPrediction;
private final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList;
@@ -38,14 +38,13 @@ public class SuggestedWords {
public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
final boolean typedWordValid,
final boolean hasAutoCorrectionCandidate,
- final boolean allowsToBeAutoCorrected,
final boolean isPunctuationSuggestions,
final boolean isObsoleteSuggestions,
final boolean isPrediction) {
mSuggestedWordInfoList = suggestedWordInfoList;
mTypedWordValid = typedWordValid;
mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate;
- mAllowsToBeAutoCorrected = allowsToBeAutoCorrected;
+ mWillAutoCorrect = !mTypedWordValid && mHasAutoCorrectionCandidate;
mIsPunctuationSuggestions = isPunctuationSuggestions;
mIsObsoleteSuggestions = isObsoleteSuggestions;
mIsPrediction = isPrediction;
@@ -72,7 +71,7 @@ public class SuggestedWords {
}
public boolean willAutoCorrect() {
- return !mTypedWordValid && mHasAutoCorrectionCandidate;
+ return mWillAutoCorrect;
}
@Override
@@ -81,7 +80,6 @@ public class SuggestedWords {
return "SuggestedWords:"
+ " mTypedWordValid=" + mTypedWordValid
+ " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate
- + " mAllowsToBeAutoCorrected=" + mAllowsToBeAutoCorrected
+ " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions
+ " words=" + Arrays.toString(mSuggestedWordInfoList.toArray());
}
@@ -91,7 +89,8 @@ public class SuggestedWords {
final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>();
for (CompletionInfo info : infos) {
if (null != info && info.getText() != null) {
- result.add(new SuggestedWordInfo(info.getText(), SuggestedWordInfo.MAX_SCORE));
+ result.add(new SuggestedWordInfo(info.getText(), SuggestedWordInfo.MAX_SCORE,
+ SuggestedWordInfo.KIND_APP_DEFINED, Dictionary.TYPE_APPLICATION_DEFINED));
}
}
return result;
@@ -103,7 +102,8 @@ public class SuggestedWords {
final CharSequence typedWord, final SuggestedWords previousSuggestions) {
final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<SuggestedWordInfo>();
final HashSet<String> alreadySeen = new HashSet<String>();
- suggestionsList.add(new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE));
+ suggestionsList.add(new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
+ SuggestedWordInfo.KIND_TYPED, Dictionary.TYPE_USER_TYPED));
alreadySeen.add(typedWord.toString());
final int previousSize = previousSuggestions.size();
for (int pos = 1; pos < previousSize; pos++) {
@@ -120,17 +120,30 @@ public class SuggestedWords {
public static class SuggestedWordInfo {
public static final int MAX_SCORE = Integer.MAX_VALUE;
+ public static final int KIND_TYPED = 0; // What user typed
+ public static final int KIND_CORRECTION = 1; // Simple correction/suggestion
+ public static final int KIND_COMPLETION = 2; // Completion (suggestion with appended chars)
+ public static final int KIND_WHITELIST = 3; // Whitelisted word
+ public static final int KIND_BLACKLIST = 4; // Blacklisted word
+ public static final int KIND_HARDCODED = 5; // Hardcoded suggestion, e.g. punctuation
+ public static final int KIND_APP_DEFINED = 6; // Suggested by the application
+ public static final int KIND_SHORTCUT = 7; // A shortcut
private final String mWordStr;
public final CharSequence mWord;
public final int mScore;
+ public final int mKind; // one of the KIND_* constants above
public final int mCodePointCount;
+ public final String mSourceDict;
private String mDebugString = "";
- public SuggestedWordInfo(final CharSequence word, final int score) {
+ public SuggestedWordInfo(final CharSequence word, final int score, final int kind,
+ final String sourceDict) {
mWordStr = word.toString();
mWord = word;
mScore = score;
- mCodePointCount = mWordStr.codePointCount(0, mWordStr.length());
+ mKind = kind;
+ mSourceDict = sourceDict;
+ mCodePointCount = StringUtils.codePointCount(mWordStr);
}
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 673b54500..9b20bd690 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -19,22 +19,23 @@ package com.android.inputmethod.latin;
import android.content.Context;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import java.util.ArrayList;
import java.util.Locale;
public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryDictionary {
private boolean mClosed;
public SynchronouslyLoadedContactsBinaryDictionary(final Context context, final Locale locale) {
- super(context, Suggest.DIC_CONTACTS, locale);
+ super(context, locale);
}
@Override
- public synchronized void getWords(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
syncReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ return getWordsInner(codes, prevWordForBigrams, proximityInfo);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsDictionary.java
deleted file mode 100644
index a8b871cdf..000000000
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsDictionary.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.Context;
-
-import com.android.inputmethod.keyboard.ProximityInfo;
-
-public class SynchronouslyLoadedContactsDictionary extends ContactsDictionary {
- private boolean mClosed;
-
- public SynchronouslyLoadedContactsDictionary(final Context context) {
- super(context, Suggest.DIC_CONTACTS);
- mClosed = false;
- }
-
- @Override
- public synchronized void getWords(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
- blockingReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- blockingReloadDictionaryIfRequired();
- return getWordFrequency(word) > -1;
- }
-
- // Protect against multiple closing
- @Override
- public synchronized void close() {
- // Actually with the current implementation of ContactsDictionary it's safe to close
- // several times, so the following protection is really only for foolproofing
- if (mClosed) return;
- mClosed = true;
- super.close();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
index 1606a34e0..5b2a6edec 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -19,6 +19,9 @@ package com.android.inputmethod.latin;
import android.content.Context;
import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary {
@@ -32,11 +35,10 @@ public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionar
}
@Override
- public synchronized void getWords(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
+ public synchronized ArrayList<SuggestedWordInfo> getWords(final WordComposer codes,
+ final CharSequence prevWordForBigrams, final ProximityInfo proximityInfo) {
syncReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+ return getWordsInner(codes, prevWordForBigrams, proximityInfo);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
deleted file mode 100644
index 23a49c192..000000000
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.Context;
-
-import com.android.inputmethod.keyboard.ProximityInfo;
-
-public class SynchronouslyLoadedUserDictionary extends UserDictionary {
- private boolean mClosed;
-
- public SynchronouslyLoadedUserDictionary(final Context context, final String locale) {
- this(context, locale, false);
- }
-
- public SynchronouslyLoadedUserDictionary(final Context context, final String locale,
- final boolean alsoUseMoreRestrictiveLocales) {
- super(context, locale, alsoUseMoreRestrictiveLocales);
- }
-
- @Override
- public synchronized void getWords(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
- blockingReloadDictionaryIfRequired();
- getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- blockingReloadDictionaryIfRequired();
- return super.isValidWord(word);
- }
-
- // Protect against multiple closing
- @Override
- public synchronized void close() {
- if (mClosed) return;
- mClosed = true;
- super.close();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 6fa1a25a1..8cef6fa20 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -36,11 +36,22 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
// TODO: use Words.SHORTCUT when it's public in the SDK
final static String SHORTCUT = "shortcut";
- private static final String[] PROJECTION_QUERY = {
- Words.WORD,
- SHORTCUT,
- Words.FREQUENCY,
- };
+ private static final String[] PROJECTION_QUERY;
+ static {
+ // 16 is JellyBean, but we want this to compile against ICS.
+ if (android.os.Build.VERSION.SDK_INT >= 16) {
+ PROJECTION_QUERY = new String[] {
+ Words.WORD,
+ SHORTCUT,
+ Words.FREQUENCY,
+ };
+ } else {
+ PROJECTION_QUERY = new String[] {
+ Words.WORD,
+ Words.FREQUENCY,
+ };
+ }
+ }
private static final String NAME = "userunigram";
@@ -58,7 +69,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
public UserBinaryDictionary(final Context context, final String locale,
final boolean alsoUseMoreRestrictiveLocales) {
- super(context, getFilenameWithLocale(NAME, locale), Suggest.DIC_USER);
+ super(context, getFilenameWithLocale(NAME, locale), Dictionary.TYPE_USER);
if (null == locale) throw new NullPointerException(); // Catch the error earlier
mLocale = locale;
mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
@@ -136,7 +147,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
requestArguments = localeElements;
}
final Cursor cursor = mContext.getContentResolver().query(
- Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null);
+ Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null);
try {
addWords(cursor);
} finally {
@@ -182,16 +193,18 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
}
private void addWords(Cursor cursor) {
+ // 16 is JellyBean, but we want this to compile against ICS.
+ final boolean hasShortcutColumn = android.os.Build.VERSION.SDK_INT >= 16;
clearFusionDictionary();
if (cursor == null) return;
if (cursor.moveToFirst()) {
final int indexWord = cursor.getColumnIndex(Words.WORD);
- final int indexShortcut = cursor.getColumnIndex(SHORTCUT);
+ final int indexShortcut = hasShortcutColumn ? cursor.getColumnIndex(SHORTCUT) : 0;
final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
while (!cursor.isAfterLast()) {
- String word = cursor.getString(indexWord);
- String shortcut = cursor.getString(indexShortcut);
- int frequency = cursor.getInt(indexFrequency);
+ final String word = cursor.getString(indexWord);
+ final String shortcut = hasShortcutColumn ? cursor.getString(indexShortcut) : null;
+ final int frequency = cursor.getInt(indexFrequency);
// Safeguard against adding really long words.
if (word.length() < MAX_WORD_LENGTH) {
super.addWord(word, null, frequency);
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
deleted file mode 100644
index c1efadd44..000000000
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.android.inputmethod.latin;
-
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.provider.UserDictionary.Words;
-import android.text.TextUtils;
-
-import com.android.inputmethod.keyboard.ProximityInfo;
-
-import java.util.Arrays;
-
-// TODO: This class is superseded by {@link UserBinaryDictionary}. Should be cleaned up.
-/**
- * An expandable dictionary that stores the words in the user unigram dictionary.
- *
- * @deprecated Use {@link UserBinaryDictionary}.
- */
-@Deprecated
-public class UserDictionary extends ExpandableDictionary {
-
- // TODO: use Words.SHORTCUT when it's public in the SDK
- final static String SHORTCUT = "shortcut";
- private static final String[] PROJECTION_QUERY = {
- Words.WORD,
- SHORTCUT,
- Words.FREQUENCY,
- };
-
- // This is not exported by the framework so we pretty much have to write it here verbatim
- private static final String ACTION_USER_DICTIONARY_INSERT =
- "com.android.settings.USER_DICTIONARY_INSERT";
-
- private ContentObserver mObserver;
- final private String mLocale;
- final private boolean mAlsoUseMoreRestrictiveLocales;
-
- public UserDictionary(final Context context, final String locale) {
- this(context, locale, false);
- }
-
- public UserDictionary(final Context context, final String locale,
- final boolean alsoUseMoreRestrictiveLocales) {
- super(context, Suggest.DIC_USER);
- if (null == locale) throw new NullPointerException(); // Catch the error earlier
- mLocale = locale;
- mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
- // Perform a managed query. The Activity will handle closing and re-querying the cursor
- // when needed.
- ContentResolver cres = context.getContentResolver();
-
- mObserver = new ContentObserver(null) {
- @Override
- public void onChange(boolean self) {
- setRequiresReload(true);
- }
- };
- cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
-
- loadDictionary();
- }
-
- @Override
- public synchronized void close() {
- if (mObserver != null) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserver = null;
- }
- super.close();
- }
-
- @Override
- public void loadDictionaryAsync() {
- // Split the locale. For example "en" => ["en"], "de_DE" => ["de", "DE"],
- // "en_US_foo_bar_qux" => ["en", "US", "foo_bar_qux"] because of the limit of 3.
- // This is correct for locale processing.
- // For this example, we'll look at the "en_US_POSIX" case.
- final String[] localeElements =
- TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3);
- final int length = localeElements.length;
-
- final StringBuilder request = new StringBuilder("(locale is NULL)");
- String localeSoFar = "";
- // At start, localeElements = ["en", "US", "POSIX"] ; localeSoFar = "" ;
- // and request = "(locale is NULL)"
- for (int i = 0; i < length; ++i) {
- // i | localeSoFar | localeElements
- // 0 | "" | ["en", "US", "POSIX"]
- // 1 | "en_" | ["en", "US", "POSIX"]
- // 2 | "en_US_" | ["en", "en_US", "POSIX"]
- localeElements[i] = localeSoFar + localeElements[i];
- localeSoFar = localeElements[i] + "_";
- // i | request
- // 0 | "(locale is NULL)"
- // 1 | "(locale is NULL) or (locale=?)"
- // 2 | "(locale is NULL) or (locale=?) or (locale=?)"
- request.append(" or (locale=?)");
- }
- // At the end, localeElements = ["en", "en_US", "en_US_POSIX"]; localeSoFar = en_US_POSIX_"
- // and request = "(locale is NULL) or (locale=?) or (locale=?) or (locale=?)"
-
- final String[] requestArguments;
- // If length == 3, we already have all the arguments we need (common prefix is meaningless
- // inside variants
- if (mAlsoUseMoreRestrictiveLocales && length < 3) {
- request.append(" or (locale like ?)");
- // The following creates an array with one more (null) position
- final String[] localeElementsWithMoreRestrictiveLocalesIncluded =
- Arrays.copyOf(localeElements, length + 1);
- localeElementsWithMoreRestrictiveLocalesIncluded[length] =
- localeElements[length - 1] + "_%";
- requestArguments = localeElementsWithMoreRestrictiveLocalesIncluded;
- // If for example localeElements = ["en"]
- // then requestArguments = ["en", "en_%"]
- // and request = (locale is NULL) or (locale=?) or (locale like ?)
- // If localeElements = ["en", "en_US"]
- // then requestArguments = ["en", "en_US", "en_US_%"]
- } else {
- requestArguments = localeElements;
- }
- final Cursor cursor = getContext().getContentResolver()
- .query(Words.CONTENT_URI, PROJECTION_QUERY, request.toString(),
- requestArguments, null);
- try {
- addWords(cursor);
- } finally {
- if (null != cursor) cursor.close();
- }
- }
-
- public boolean isEnabled() {
- final ContentResolver cr = getContext().getContentResolver();
- final ContentProviderClient client = cr.acquireContentProviderClient(Words.CONTENT_URI);
- if (client != null) {
- client.release();
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Adds a word to the user dictionary and makes it persistent.
- *
- * This will call upon the system interface to do the actual work through the intent
- * readied by the system to this effect.
- *
- * @param word the word to add. If the word is capitalized, then the dictionary will
- * recognize it as a capitalized word when searched.
- * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
- * the highest.
- * @TODO use a higher or float range for frequency
- */
- public synchronized void addWordToUserDictionary(final String word, final int frequency) {
- // Force load the dictionary here synchronously
- if (getRequiresReload()) loadDictionaryAsync();
- // TODO: do something for the UI. With the following, any sufficiently long word will
- // look like it will go to the user dictionary but it won't.
- // Safeguard against adding long words. Can cause stack overflow.
- if (word.length() >= getMaxWordLength()) return;
-
- // TODO: Add an argument to the intent to specify the frequency.
- Intent intent = new Intent(ACTION_USER_DICTIONARY_INSERT);
- intent.putExtra(Words.WORD, word);
- intent.putExtra(Words.LOCALE, mLocale);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getContext().startActivity(intent);
- }
-
- @Override
- public synchronized void getWords(final WordComposer codes,
- final CharSequence prevWordForBigrams, final WordCallback callback,
- final ProximityInfo proximityInfo) {
- super.getWords(codes, prevWordForBigrams, callback, proximityInfo);
- }
-
- @Override
- public synchronized boolean isValidWord(CharSequence word) {
- return super.isValidWord(word);
- }
-
- private void addWords(Cursor cursor) {
- clearDictionary();
- if (cursor == null) return;
- final int maxWordLength = getMaxWordLength();
- if (cursor.moveToFirst()) {
- final int indexWord = cursor.getColumnIndex(Words.WORD);
- final int indexShortcut = cursor.getColumnIndex(SHORTCUT);
- final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
- while (!cursor.isAfterLast()) {
- String word = cursor.getString(indexWord);
- String shortcut = cursor.getString(indexShortcut);
- int frequency = cursor.getInt(indexFrequency);
- // Safeguard against adding really long words. Stack may overflow due
- // to recursion
- if (word.length() < maxWordLength) {
- super.addWord(word, null, frequency);
- }
- if (null != shortcut && shortcut.length() < maxWordLength) {
- super.addWord(shortcut, word, frequency);
- }
- cursor.moveToNext();
- }
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
index 5095f6582..73fa83f9a 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -115,8 +115,7 @@ public class UserHistoryDictionary extends ExpandableDictionary {
}
public synchronized static UserHistoryDictionary getInstance(
- final Context context, final String locale,
- final int dictTypeId, final SharedPreferences sp) {
+ final Context context, final String locale, final SharedPreferences sp) {
if (sLangDictCache.containsKey(locale)) {
final SoftReference<UserHistoryDictionary> ref = sLangDictCache.get(locale);
final UserHistoryDictionary dict = ref == null ? null : ref.get();
@@ -128,14 +127,14 @@ public class UserHistoryDictionary extends ExpandableDictionary {
}
}
final UserHistoryDictionary dict =
- new UserHistoryDictionary(context, locale, dictTypeId, sp);
+ new UserHistoryDictionary(context, locale, sp);
sLangDictCache.put(locale, new SoftReference<UserHistoryDictionary>(dict));
return dict;
}
- private UserHistoryDictionary(final Context context, final String locale, final int dicTypeId,
- SharedPreferences sp) {
- super(context, dicTypeId);
+ private UserHistoryDictionary(final Context context, final String locale,
+ final SharedPreferences sp) {
+ super(context, Dictionary.TYPE_USER_HISTORY);
mLocale = locale;
mPrefs = sp;
if (sOpenHelper == null) {
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java
index e5516dc62..1de95d7b8 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java
@@ -50,7 +50,7 @@ public class UserHistoryForgettingCurveUtils {
}
private ForgettingCurveParams(long now, boolean isValid) {
- this((int)pushCount((byte)0, isValid), now, now, isValid);
+ this(pushCount((byte)0, isValid), now, now, isValid);
}
/** This constructor is called when the user history bigram dictionary is being restored. */
@@ -199,20 +199,20 @@ public class UserHistoryForgettingCurveUtils {
public static final int[][] SCORE_TABLE = new int[FC_LEVEL_MAX][ELAPSED_TIME_MAX + 1];
static {
for (int i = 0; i < FC_LEVEL_MAX; ++i) {
- final double initialFreq;
+ final float initialFreq;
if (i >= 2) {
- initialFreq = (double)FC_FREQ_MAX;
+ initialFreq = FC_FREQ_MAX;
} else if (i == 1) {
- initialFreq = (double)FC_FREQ_MAX / 2;
+ initialFreq = FC_FREQ_MAX / 2;
} else if (i == 0) {
- initialFreq = (double)FC_FREQ_MAX / 4;
+ initialFreq = FC_FREQ_MAX / 4;
} else {
continue;
}
for (int j = 0; j < ELAPSED_TIME_MAX; ++j) {
- final double elapsedHour = j * ELAPSED_TIME_INTERVAL_HOURS;
- final double freq =
- initialFreq * Math.pow(initialFreq, elapsedHour / HALF_LIFE_HOURS);
+ final float elapsedHours = j * ELAPSED_TIME_INTERVAL_HOURS;
+ final float freq = initialFreq
+ * NativeUtils.powf(initialFreq, elapsedHours / HALF_LIFE_HOURS);
final int intFreq = Math.min(FC_FREQ_MAX, Math.max(0, (int)freq));
SCORE_TABLE[i][j] = intFreq;
}
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 4178955bc..8f71de0e7 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -44,10 +44,9 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
-import java.util.Map;
public class Utils {
private Utils() {
@@ -206,18 +205,24 @@ public class Utils {
}
// Get the current stack trace
- public static String getStackTrace() {
+ public static String getStackTrace(final int limit) {
StringBuilder sb = new StringBuilder();
try {
throw new RuntimeException();
} catch (RuntimeException e) {
StackTraceElement[] frames = e.getStackTrace();
// Start at 1 because the first frame is here and we don't care about it
- for (int j = 1; j < frames.length; ++j) sb.append(frames[j].toString() + "\n");
+ for (int j = 1; j < frames.length && j < limit + 1; ++j) {
+ sb.append(frames[j].toString() + "\n");
+ }
}
return sb.toString();
}
+ public static String getStackTrace() {
+ return getStackTrace(Integer.MAX_VALUE);
+ }
+
public static class UsabilityStudyLogUtils {
// TODO: remove code duplication with ResearchLog class
private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName();
diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
index a0de2f970..3af22140e 100644
--- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
+++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java
@@ -37,7 +37,7 @@ public class WhitelistDictionary extends ExpandableDictionary {
// TODO: Conform to the async load contact of ExpandableDictionary
public WhitelistDictionary(final Context context, final Locale locale) {
- super(context, Suggest.DIC_WHITELIST);
+ super(context, Dictionary.TYPE_WHITELIST);
// TODO: Move whitelist dictionary into main dictionary.
final RunInLocale<Void> job = new RunInLocale<Void>() {
@Override
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index ca9caa1d3..98282f970 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -34,8 +34,7 @@ public class WordComposer {
private static final int N = BinaryDictionary.MAX_WORD_LENGTH;
private int[] mPrimaryKeyCodes;
- private int[] mXCoordinates;
- private int[] mYCoordinates;
+ private final InputPointers mInputPointers = new InputPointers();
private StringBuilder mTypedWord;
private CharSequence mAutoCorrection;
private boolean mIsResumed;
@@ -54,8 +53,6 @@ public class WordComposer {
public WordComposer() {
mPrimaryKeyCodes = new int[N];
mTypedWord = new StringBuilder(N);
- mXCoordinates = new int[N];
- mYCoordinates = new int[N];
mAutoCorrection = null;
mTrailingSingleQuotesCount = 0;
mIsResumed = false;
@@ -69,8 +66,7 @@ public class WordComposer {
public void init(WordComposer source) {
mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length);
mTypedWord = new StringBuilder(source.mTypedWord);
- mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length);
- mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length);
+ mInputPointers.copy(source.mInputPointers);
mCapsCount = source.mCapsCount;
mIsFirstCharCapitalized = source.mIsFirstCharCapitalized;
mAutoCapitalized = source.mAutoCapitalized;
@@ -92,7 +88,7 @@ public class WordComposer {
refreshSize();
}
- public final void refreshSize() {
+ private final void refreshSize() {
mCodePointSize = mTypedWord.codePointCount(0, mTypedWord.length());
}
@@ -116,12 +112,8 @@ public class WordComposer {
return mPrimaryKeyCodes[index];
}
- public int[] getXCoordinates() {
- return mXCoordinates;
- }
-
- public int[] getYCoordinates() {
- return mYCoordinates;
+ public InputPointers getInputPointers() {
+ return mInputPointers;
}
private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) {
@@ -157,8 +149,8 @@ public class WordComposer {
if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE
? Character.toLowerCase(primaryCode) : primaryCode;
- mXCoordinates[newIndex] = keyX;
- mYCoordinates[newIndex] = keyY;
+ // TODO: Set correct pointer id and time
+ mInputPointers.addPointer(newIndex, keyX, keyY, 0, 0);
}
mIsFirstCharCapitalized = isFirstCharCapitalized(
newIndex, primaryCode, mIsFirstCharCapitalized);
@@ -318,14 +310,11 @@ public class WordComposer {
// or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
// the last composed word to ensure this does not happen.
final int[] primaryKeyCodes = mPrimaryKeyCodes;
- final int[] xCoordinates = mXCoordinates;
- final int[] yCoordinates = mYCoordinates;
mPrimaryKeyCodes = new int[N];
- mXCoordinates = new int[N];
- mYCoordinates = new int[N];
final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes,
- xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode,
+ mInputPointers, mTypedWord.toString(), committedWord, separatorCode,
prevWord);
+ mInputPointers.reset();
if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
&& type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
lastComposedWord.deactivate();
@@ -339,8 +328,7 @@ public class WordComposer {
public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) {
mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes;
- mXCoordinates = lastComposedWord.mXCoordinates;
- mYCoordinates = lastComposedWord.mYCoordinates;
+ mInputPointers.set(lastComposedWord.mInputPointers);
mTypedWord.setLength(0);
mTypedWord.append(lastComposedWord.mTypedWord);
refreshSize();
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index 89c59f809..2c3eee74c 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -787,9 +787,9 @@ public class BinaryDictInputOutput {
// (discretizedFrequency + 0.5) times this value to get the median value of the step,
// which is the best approximation. This is how we get the most precise result with
// only four bits.
- final double stepSize =
- (double)(MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5 + MAX_BIGRAM_FREQUENCY);
- final double firstStepStart = 1 + unigramFrequency + (stepSize / 2.0);
+ final float stepSize =
+ (MAX_TERMINAL_FREQUENCY - unigramFrequency) / (1.5f + MAX_BIGRAM_FREQUENCY);
+ final float firstStepStart = 1 + unigramFrequency + (stepSize / 2.0f);
final int discretizedFrequency = (int)((bigramFrequency - firstStepStart) / stepSize);
// If the bigram freq is less than half-a-step higher than the unigram freq, we get -1
// here. The best approximation would be the unigram freq itself, so we should not
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 88efc5a85..5f4d66091 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -30,18 +30,17 @@ import android.view.textservice.TextInfo;
import com.android.inputmethod.compat.SuggestionsInfoCompatUtils;
import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.ContactsBinaryDictionary;
import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.Dictionary.WordCallback;
import com.android.inputmethod.latin.DictionaryCollection;
import com.android.inputmethod.latin.DictionaryFactory;
-import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StringUtils;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.SynchronouslyLoadedContactsBinaryDictionary;
-import com.android.inputmethod.latin.SynchronouslyLoadedContactsDictionary;
import com.android.inputmethod.latin.SynchronouslyLoadedUserBinaryDictionary;
-import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary;
+import com.android.inputmethod.latin.UserBinaryDictionary;
import com.android.inputmethod.latin.WhitelistDictionary;
import com.android.inputmethod.latin.WordComposer;
@@ -73,11 +72,11 @@ public class AndroidSpellCheckerService extends SpellCheckerService
private final static String[] EMPTY_STRING_ARRAY = new String[0];
private Map<String, DictionaryPool> mDictionaryPools =
Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
- private Map<String, Dictionary> mUserDictionaries =
- Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+ private Map<String, UserBinaryDictionary> mUserDictionaries =
+ Collections.synchronizedMap(new TreeMap<String, UserBinaryDictionary>());
private Map<String, Dictionary> mWhitelistDictionaries =
Collections.synchronizedMap(new TreeMap<String, Dictionary>());
- private Dictionary mContactsDictionary;
+ private ContactsBinaryDictionary mContactsDictionary;
// The threshold for a candidate to be offered as a suggestion.
private float mSuggestionThreshold;
@@ -154,13 +153,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService
private void startUsingContactsDictionaryLocked() {
if (null == mContactsDictionary) {
- if (LatinIME.USE_BINARY_CONTACTS_DICTIONARY) {
- // TODO: use the right locale for each session
- mContactsDictionary =
- new SynchronouslyLoadedContactsBinaryDictionary(this, Locale.getDefault());
- } else {
- mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
- }
+ // TODO: use the right locale for each session
+ mContactsDictionary =
+ new SynchronouslyLoadedContactsBinaryDictionary(this, Locale.getDefault());
}
final Iterator<WeakReference<DictionaryCollection>> iterator =
mDictionaryCollectionsList.iterator();
@@ -208,7 +203,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
EMPTY_STRING_ARRAY);
}
- private static class SuggestionsGatherer implements WordCallback {
+ // TODO: remove this class and replace it by storage local to the session.
+ private static class SuggestionsGatherer {
public static class Result {
public final String[] mSuggestions;
public final boolean mHasRecommendedSuggestions;
@@ -242,9 +238,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
mScores = new int[mMaxLength];
}
- @Override
- synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score,
- int dicTypeId, int dataType) {
+ synchronized public boolean addWord(char[] word, int[] spaceIndices, int wordOffset,
+ int wordLength, int score) {
final int positionIndex = Arrays.binarySearch(mScores, 0, mLength, score);
// binarySearch returns the index if the element exists, and -<insertion index> - 1
// if it doesn't. See documentation for binarySearch.
@@ -368,8 +363,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService
private void closeAllDictionaries() {
final Map<String, DictionaryPool> oldPools = mDictionaryPools;
mDictionaryPools = Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
- final Map<String, Dictionary> oldUserDictionaries = mUserDictionaries;
- mUserDictionaries = Collections.synchronizedMap(new TreeMap<String, Dictionary>());
+ final Map<String, UserBinaryDictionary> oldUserDictionaries = mUserDictionaries;
+ mUserDictionaries =
+ Collections.synchronizedMap(new TreeMap<String, UserBinaryDictionary>());
final Map<String, Dictionary> oldWhitelistDictionaries = mWhitelistDictionaries;
mWhitelistDictionaries = Collections.synchronizedMap(new TreeMap<String, Dictionary>());
new Thread("spellchecker_close_dicts") {
@@ -389,7 +385,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
// The synchronously loaded contacts dictionary should have been in one
// or several pools, but it is shielded against multiple closing and it's
// safe to call it several times.
- final Dictionary dictToClose = mContactsDictionary;
+ final ContactsBinaryDictionary dictToClose = mContactsDictionary;
// TODO: revert to the concrete type when USE_BINARY_CONTACTS_DICTIONARY
// is no longer needed
mContactsDictionary = null;
@@ -421,13 +417,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService
DictionaryFactory.createMainDictionaryFromManager(this, locale,
true /* useFullEditDistance */);
final String localeStr = locale.toString();
- Dictionary userDictionary = mUserDictionaries.get(localeStr);
+ UserBinaryDictionary userDictionary = mUserDictionaries.get(localeStr);
if (null == userDictionary) {
- if (LatinIME.USE_BINARY_USER_DICTIONARY) {
- userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, localeStr, true);
- } else {
- userDictionary = new SynchronouslyLoadedUserDictionary(this, localeStr, true);
- }
+ userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, localeStr, true);
mUserDictionaries.put(localeStr, userDictionary);
}
dictionaryCollection.addDictionary(userDictionary);
@@ -440,17 +432,11 @@ public class AndroidSpellCheckerService extends SpellCheckerService
synchronized (mUseContactsLock) {
if (mUseContactsDictionary) {
if (null == mContactsDictionary) {
- // TODO: revert to the concrete type when USE_BINARY_CONTACTS_DICTIONARY is no
- // longer needed
- if (LatinIME.USE_BINARY_CONTACTS_DICTIONARY) {
- // TODO: use the right locale. We can't do it right now because the
- // spell checker is reusing the contacts dictionary across sessions
- // without regard for their locale, so we need to fix that first.
- mContactsDictionary = new SynchronouslyLoadedContactsBinaryDictionary(this,
- Locale.getDefault());
- } else {
- mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this);
- }
+ // TODO: use the right locale. We can't do it right now because the
+ // spell checker is reusing the contacts dictionary across sessions
+ // without regard for their locale, so we need to fix that first.
+ mContactsDictionary = new SynchronouslyLoadedContactsBinaryDictionary(this,
+ Locale.getDefault());
}
}
dictionaryCollection.addDictionary(mContactsDictionary);
@@ -501,20 +487,32 @@ public class AndroidSpellCheckerService extends SpellCheckerService
}
private static class SuggestionsCache {
+ private static final char CHAR_DELIMITER = '\uFFFC';
private static final int MAX_CACHE_SIZE = 50;
- // TODO: support bigram
private final LruCache<String, SuggestionsParams> mUnigramSuggestionsInfoCache =
new LruCache<String, SuggestionsParams>(MAX_CACHE_SIZE);
- public SuggestionsParams getSuggestionsFromCache(String query) {
- return mUnigramSuggestionsInfoCache.get(query);
+ // TODO: Support n-gram input
+ private static String generateKey(String query, String prevWord) {
+ if (TextUtils.isEmpty(query) || TextUtils.isEmpty(prevWord)) {
+ return query;
+ }
+ return query + CHAR_DELIMITER + prevWord;
+ }
+
+ // TODO: Support n-gram input
+ public SuggestionsParams getSuggestionsFromCache(String query, String prevWord) {
+ return mUnigramSuggestionsInfoCache.get(generateKey(query, prevWord));
}
- public void putSuggestionsToCache(String query, String[] suggestions, int flags) {
+ // TODO: Support n-gram input
+ public void putSuggestionsToCache(
+ String query, String prevWord, String[] suggestions, int flags) {
if (suggestions == null || TextUtils.isEmpty(query)) {
return;
}
- mUnigramSuggestionsInfoCache.put(query, new SuggestionsParams(suggestions, flags));
+ mUnigramSuggestionsInfoCache.put(
+ generateKey(query, prevWord), new SuggestionsParams(suggestions, flags));
}
}
@@ -609,6 +607,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
final ArrayList<Integer> additionalLengths = new ArrayList<Integer>();
final ArrayList<SuggestionsInfo> additionalSuggestionsInfos =
new ArrayList<SuggestionsInfo>();
+ String currentWord = null;
for (int i = 0; i < N; ++i) {
final SuggestionsInfo si = ssi.getSuggestionsInfoAt(i);
final int flags = si.getSuggestionsAttributes();
@@ -618,6 +617,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
final int offset = ssi.getOffsetAt(i);
final int length = ssi.getLengthAt(i);
final String subText = typedText.substring(offset, offset + length);
+ final String prevWord = currentWord;
+ currentWord = subText;
if (!subText.contains(SINGLE_QUOTE)) {
continue;
}
@@ -631,7 +632,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService
if (TextUtils.isEmpty(splitText)) {
continue;
}
- if (mSuggestionsCache.getSuggestionsFromCache(splitText) == null) {
+ if (mSuggestionsCache.getSuggestionsFromCache(
+ splitText, prevWord) == null) {
continue;
}
final int newLength = splitText.length();
@@ -727,7 +729,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
try {
final String inText = textInfo.getText();
final SuggestionsParams cachedSuggestionsParams =
- mSuggestionsCache.getSuggestionsFromCache(inText);
+ mSuggestionsCache.getSuggestionsFromCache(inText, prevWord);
if (cachedSuggestionsParams != null) {
if (DBG) {
Log.d(TAG, "Cache hit: " + inText + ", " + cachedSuggestionsParams.mFlags);
@@ -778,8 +780,13 @@ public class AndroidSpellCheckerService extends SpellCheckerService
try {
dictInfo = mDictionaryPool.takeOrGetNull();
if (null == dictInfo) return getNotInDictEmptySuggestions();
- dictInfo.mDictionary.getWords(composer, prevWord, suggestionsGatherer,
- dictInfo.mProximityInfo);
+ final ArrayList<SuggestedWordInfo> suggestions = dictInfo.mDictionary.getWords(
+ composer, prevWord, dictInfo.mProximityInfo);
+ for (final SuggestedWordInfo suggestion : suggestions) {
+ final String suggestionStr = suggestion.mWord.toString();
+ suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0,
+ suggestionStr.length(), suggestion.mScore);
+ }
isInDict = dictInfo.mDictionary.isValidWord(text);
if (!isInDict && CAPITALIZE_NONE != capitalizeType) {
// We want to test the word again if it's all caps or first caps only.
@@ -819,7 +826,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
.getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS()
: 0);
final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
- mSuggestionsCache.putSuggestionsToCache(text, result.mSuggestions, flags);
+ mSuggestionsCache.putSuggestionsToCache(text, prevWord, result.mSuggestions, flags);
return retval;
} catch (RuntimeException e) {
// Don't kill the keyboard if there is a bug in the spell checker
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
index e86390b11..f087790f6 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
@@ -336,9 +336,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
if (LatinImeLogger.sDBG && suggestedWords.size() > 1) {
// If we auto-correct, then the autocorrection is in slot 0 and the typed word
// is in slot 1.
- if (index == mCenterSuggestionIndex && suggestedWords.mHasAutoCorrectionCandidate
- && Suggest.shouldBlockAutoCorrectionBySafetyNet(
- suggestedWords.getWord(1).toString(), suggestedWords.getWord(0))) {
+ if (index == mCenterSuggestionIndex && Suggest.shouldBlockAutoCorrectionBySafetyNet(
+ suggestedWords.getWord(1).toString(), suggestedWords.getWord(0))) {
return 0xFFFF0000;
}
}