diff options
196 files changed, 1379 insertions, 1014 deletions
diff --git a/dictionaries/cs_wordlist.combined.gz b/dictionaries/cs_wordlist.combined.gz Binary files differindex 7829d6573..94ba863a2 100644 --- a/dictionaries/cs_wordlist.combined.gz +++ b/dictionaries/cs_wordlist.combined.gz diff --git a/dictionaries/da_wordlist.combined.gz b/dictionaries/da_wordlist.combined.gz Binary files differindex e7140195b..b4baf627f 100644 --- a/dictionaries/da_wordlist.combined.gz +++ b/dictionaries/da_wordlist.combined.gz diff --git a/dictionaries/de_wordlist.combined.gz b/dictionaries/de_wordlist.combined.gz Binary files differindex 6a4bd445c..400718df1 100644 --- a/dictionaries/de_wordlist.combined.gz +++ b/dictionaries/de_wordlist.combined.gz diff --git a/dictionaries/el_wordlist.combined.gz b/dictionaries/el_wordlist.combined.gz Binary files differindex 74effa34b..599734cf8 100644 --- a/dictionaries/el_wordlist.combined.gz +++ b/dictionaries/el_wordlist.combined.gz diff --git a/dictionaries/en_GB_wordlist.combined.gz b/dictionaries/en_GB_wordlist.combined.gz Binary files differindex ff69f64c8..22685d1ce 100644 --- a/dictionaries/en_GB_wordlist.combined.gz +++ b/dictionaries/en_GB_wordlist.combined.gz diff --git a/dictionaries/en_US_wordlist.combined.gz b/dictionaries/en_US_wordlist.combined.gz Binary files differindex 2c80bc49d..92a3761df 100644 --- a/dictionaries/en_US_wordlist.combined.gz +++ b/dictionaries/en_US_wordlist.combined.gz diff --git a/dictionaries/en_emoji.combined.gz b/dictionaries/en_emoji.combined.gz Binary files differindex 0fc009df7..4d9cf1b59 100644 --- a/dictionaries/en_emoji.combined.gz +++ b/dictionaries/en_emoji.combined.gz diff --git a/dictionaries/en_wordlist.combined.gz b/dictionaries/en_wordlist.combined.gz Binary files differindex 06fb64fe8..f8b71c821 100644 --- a/dictionaries/en_wordlist.combined.gz +++ b/dictionaries/en_wordlist.combined.gz diff --git a/dictionaries/es_wordlist.combined.gz b/dictionaries/es_wordlist.combined.gz Binary files differindex 0a48b6d11..56617db99 100644 --- a/dictionaries/es_wordlist.combined.gz +++ b/dictionaries/es_wordlist.combined.gz diff --git a/dictionaries/fi_wordlist.combined.gz b/dictionaries/fi_wordlist.combined.gz Binary files differindex eefbfe51a..b7332ad3e 100644 --- a/dictionaries/fi_wordlist.combined.gz +++ b/dictionaries/fi_wordlist.combined.gz diff --git a/dictionaries/fr_emoji.combined.gz b/dictionaries/fr_emoji.combined.gz Binary files differindex f2929770d..5c9c7a096 100644 --- a/dictionaries/fr_emoji.combined.gz +++ b/dictionaries/fr_emoji.combined.gz diff --git a/dictionaries/fr_wordlist.combined.gz b/dictionaries/fr_wordlist.combined.gz Binary files differindex b568838e4..697f36799 100644 --- a/dictionaries/fr_wordlist.combined.gz +++ b/dictionaries/fr_wordlist.combined.gz diff --git a/dictionaries/hr_wordlist.combined.gz b/dictionaries/hr_wordlist.combined.gz Binary files differindex 864f67651..9a2086f1f 100644 --- a/dictionaries/hr_wordlist.combined.gz +++ b/dictionaries/hr_wordlist.combined.gz diff --git a/dictionaries/it_wordlist.combined.gz b/dictionaries/it_wordlist.combined.gz Binary files differindex ac977e303..5a5cbdc7a 100644 --- a/dictionaries/it_wordlist.combined.gz +++ b/dictionaries/it_wordlist.combined.gz diff --git a/dictionaries/iw_wordlist.combined.gz b/dictionaries/iw_wordlist.combined.gz Binary files differindex 36b047894..13eab9f17 100644 --- a/dictionaries/iw_wordlist.combined.gz +++ b/dictionaries/iw_wordlist.combined.gz diff --git a/dictionaries/lt_wordlist.combined.gz b/dictionaries/lt_wordlist.combined.gz Binary files differindex 029722d95..961266bb8 100644 --- a/dictionaries/lt_wordlist.combined.gz +++ b/dictionaries/lt_wordlist.combined.gz diff --git a/dictionaries/lv_wordlist.combined.gz b/dictionaries/lv_wordlist.combined.gz Binary files differindex 41e1c28bd..ae906a9db 100644 --- a/dictionaries/lv_wordlist.combined.gz +++ b/dictionaries/lv_wordlist.combined.gz diff --git a/dictionaries/nb_wordlist.combined.gz b/dictionaries/nb_wordlist.combined.gz Binary files differindex b699912b7..1c0f2cfb9 100644 --- a/dictionaries/nb_wordlist.combined.gz +++ b/dictionaries/nb_wordlist.combined.gz diff --git a/dictionaries/nl_wordlist.combined.gz b/dictionaries/nl_wordlist.combined.gz Binary files differindex 89c238830..37ba8ab42 100644 --- a/dictionaries/nl_wordlist.combined.gz +++ b/dictionaries/nl_wordlist.combined.gz diff --git a/dictionaries/pl_wordlist.combined.gz b/dictionaries/pl_wordlist.combined.gz Binary files differindex 2b53f69cb..ba71a5581 100644 --- a/dictionaries/pl_wordlist.combined.gz +++ b/dictionaries/pl_wordlist.combined.gz diff --git a/dictionaries/pt_BR_wordlist.combined.gz b/dictionaries/pt_BR_wordlist.combined.gz Binary files differindex 2d22447e4..02df1c1ee 100644 --- a/dictionaries/pt_BR_wordlist.combined.gz +++ b/dictionaries/pt_BR_wordlist.combined.gz diff --git a/dictionaries/pt_PT_wordlist.combined.gz b/dictionaries/pt_PT_wordlist.combined.gz Binary files differindex 1504165d0..bcd50ab03 100644 --- a/dictionaries/pt_PT_wordlist.combined.gz +++ b/dictionaries/pt_PT_wordlist.combined.gz diff --git a/dictionaries/ru_wordlist.combined.gz b/dictionaries/ru_wordlist.combined.gz Binary files differindex 8e654e9a1..acde9bc73 100644 --- a/dictionaries/ru_wordlist.combined.gz +++ b/dictionaries/ru_wordlist.combined.gz diff --git a/dictionaries/sl_wordlist.combined.gz b/dictionaries/sl_wordlist.combined.gz Binary files differindex 55e1bb1c8..a7240fe5b 100644 --- a/dictionaries/sl_wordlist.combined.gz +++ b/dictionaries/sl_wordlist.combined.gz diff --git a/dictionaries/sr_wordlist.combined.gz b/dictionaries/sr_wordlist.combined.gz Binary files differindex 8488a08b4..30ce99670 100644 --- a/dictionaries/sr_wordlist.combined.gz +++ b/dictionaries/sr_wordlist.combined.gz diff --git a/dictionaries/sv_wordlist.combined.gz b/dictionaries/sv_wordlist.combined.gz Binary files differindex 63425206e..b6ebab320 100644 --- a/dictionaries/sv_wordlist.combined.gz +++ b/dictionaries/sv_wordlist.combined.gz diff --git a/dictionaries/tr_wordlist.combined.gz b/dictionaries/tr_wordlist.combined.gz Binary files differindex 0251778c7..306cea184 100644 --- a/dictionaries/tr_wordlist.combined.gz +++ b/dictionaries/tr_wordlist.combined.gz diff --git a/java/res/color/key_text_color_holo.xml b/java/res/color/key_text_color_holo.xml deleted file mode 100644 index d034a945f..000000000 --- a/java/res/color/key_text_color_holo.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2013 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- Functional keys. --> - <item android:state_single="true" android:state_pressed="true" - android:color="@color/key_text_color_functional_holo" /> - <item android:state_single="true" - android:color="@color/key_text_color_functional_holo" /> - - <!-- Action keys. --> - <item android:state_active="true" android:state_pressed="true" - android:color="@color/key_text_color_normal_holo" /> - <item android:state_active="true" - android:color="@color/key_text_color_normal_holo" /> - - <!-- Toggle keys. Use checkable/checked state. --> - <item android:state_checkable="true" android:state_checked="true" android:state_pressed="true" - android:color="@color/key_text_color_normal_holo" /> - <item android:state_checkable="true" android:state_pressed="true" - android:color="@color/key_text_color_normal_holo" /> - <item android:state_checkable="true" android:state_checked="true" - android:color="@color/key_text_color_normal_holo" /> - <item android:state_checkable="true" - android:color="@color/key_text_color_normal_holo" /> - - <!-- Empty background keys. --> - <item android:state_empty="true" - android:color="@color/key_text_color_normal_holo" /> - - <!-- Normal keys. --> - <item android:state_pressed="true" - android:color="@color/key_text_color_normal_holo" /> - <item android:color="@color/key_text_color_normal_holo" /> -</selector> diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict Binary files differindex c65698d7b..3cbf7105d 100644 --- a/java/res/raw/main_de.dict +++ b/java/res/raw/main_de.dict diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict Binary files differindex 57f3fe7c1..49adc9a19 100644 --- a/java/res/raw/main_en.dict +++ b/java/res/raw/main_en.dict diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict Binary files differindex 261ab8c87..fe24cd624 100644 --- a/java/res/raw/main_es.dict +++ b/java/res/raw/main_es.dict diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict Binary files differindex c240d9665..94d1b9670 100644 --- a/java/res/raw/main_fr.dict +++ b/java/res/raw/main_fr.dict diff --git a/java/res/raw/main_it.dict b/java/res/raw/main_it.dict Binary files differindex 98135ce8e..ff11b9798 100644 --- a/java/res/raw/main_it.dict +++ b/java/res/raw/main_it.dict diff --git a/java/res/raw/main_pt_br.dict b/java/res/raw/main_pt_br.dict Binary files differindex 21bbe7c67..9fa50442a 100644 --- a/java/res/raw/main_pt_br.dict +++ b/java/res/raw/main_pt_br.dict diff --git a/java/res/raw/main_ru.dict b/java/res/raw/main_ru.dict Binary files differindex c2b1e67b3..0f08f1735 100644 --- a/java/res/raw/main_ru.dict +++ b/java/res/raw/main_ru.dict diff --git a/java/res/values-af/strings-config-important-notice.xml b/java/res/values-af/strings-config-important-notice.xml index d0f328fd3..7c4dea563 100644 --- a/java/res/values-af/strings-config-important-notice.xml +++ b/java/res/values-af/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Leer uit jou kommunikasie en getikte data om voorstelle te verbeter"</string> </resources> diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml index df43b13c7..59494aaff 100644 --- a/java/res/values-af/strings.xml +++ b/java/res/values-af/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Kies \'n woordeboeklêer om te installeer"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Moet hierdie lêer regtig vir <xliff:g id="LANGUAGE_NAME">%s</xliff:g> geïnstalleer word?"</string> <string name="error" msgid="8940763624668513648">"Daar was \'n fout"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Gooi kontaktewoordeboek weg"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Gooi persoonlike woordeboek weg"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Gooi gebruikergeskiedeniswoordeboek weg"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Gooi personaliseringwoordeboek weg"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Lys kontaktewoordeboek"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Lys persoonlike woordeboek"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Lys gebruikergeskiedeniswoordeboek"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Lys personaliseringwoordeboek"</string> <string name="button_default" msgid="3988017840431881491">"Verstek"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Welkom by <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"met Gebaar-tik"</string> diff --git a/java/res/values-am/strings-config-important-notice.xml b/java/res/values-am/strings-config-important-notice.xml index 5bef0436c..ad64b6aca 100644 --- a/java/res/values-am/strings-config-important-notice.xml +++ b/java/res/values-am/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"የአስተያየት ጥቆማዎችን ለማሻሻል ከእርስዎ ግንኙነቶች እና የተተየበ ውሂብ ይማሩ"</string> </resources> diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml index 3921fd135..6d4c5bf88 100644 --- a/java/res/values-am/strings.xml +++ b/java/res/values-am/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"የሚጭኑት የመዝገበ-ቃላት ፋይል ይምረጡ"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"እውን ይሄ ፋይል ለ<xliff:g id="LANGUAGE_NAME">%s</xliff:g> ይጫን?"</string> <string name="error" msgid="8940763624668513648">"ስህተት ተከስቶ ነበር"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"የእውቂያዎች መዝገበ-ቃላትን ያራግፉ"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"የግል መዝገበ-ቃላትን ያራግፉ"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"የተጠቃሚ ታሪክ መዝገበ-ቃላትን ያራግፉ"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"የግላዊነት ማላበሻ መዝገበ-ቃላትን ያራግፉ"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"የእውቂያዎች መዝገበ-ቃላትን ዝርዝር ይፍጠሩ"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"የግል መዝገበ-ቃላትን ዝርዝር ይፍጠሩ"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"የተጠቃሚ ታሪክ መዝገበ-ቃላትን ዝርዝር ይፍጠሩ"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"የግላዊነት ማላበሻ መዝገበ-ቃላትን ዝርዝር ይፍጠሩ"</string> <string name="button_default" msgid="3988017840431881491">"ነባሪ"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"እንኳን ወደ <xliff:g id="APPLICATION_NAME">%s</xliff:g> በደህና መጡ"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"በጣት ምልክት መተየብ"</string> diff --git a/java/res/values-ar/strings-config-important-notice.xml b/java/res/values-ar/strings-config-important-notice.xml index 36600af24..5e716c4a0 100644 --- a/java/res/values-ar/strings-config-important-notice.xml +++ b/java/res/values-ar/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"التعلم من اتصالاتك والبيانات التي تكتبها لتحسين الاقتراحات"</string> </resources> diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml index a0c26cf9c..f6ac11768 100644 --- a/java/res/values-ar/strings.xml +++ b/java/res/values-ar/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"تحديد ملف قاموس للتثبيت"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"هل تريد حقًا تثبيت هذا الملف للغة <xliff:g id="LANGUAGE_NAME">%s</xliff:g>؟"</string> <string name="error" msgid="8940763624668513648">"حدث خطأ"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"تفريغ معجم جهات الاتصال"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"عرض جهات الاتصال"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"تفريغ المعجم الشخصي"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"تفريغ معجم سجل المستخدم"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"تفريغ معجم التخصيص"</string> diff --git a/java/res/values-az-rAZ/strings-config-important-notice.xml b/java/res/values-az-rAZ/strings-config-important-notice.xml index 1815443c2..fa6f9522d 100644 --- a/java/res/values-az-rAZ/strings-config-important-notice.xml +++ b/java/res/values-az-rAZ/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Əlaqələrdən və təkliflərin inkişafı üçün yazdığınız datadan öyrənin "</string> </resources> diff --git a/java/res/values-bg/strings-config-important-notice.xml b/java/res/values-bg/strings-config-important-notice.xml index b6b766637..06f14087f 100644 --- a/java/res/values-bg/strings-config-important-notice.xml +++ b/java/res/values-bg/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Ползване на съобщ. ви и въведени от вас данни за подобр. на предлож."</string> </resources> diff --git a/java/res/values-ca/strings-config-important-notice.xml b/java/res/values-ca/strings-config-important-notice.xml index eadb5695e..57a7ade17 100644 --- a/java/res/values-ca/strings-config-important-notice.xml +++ b/java/res/values-ca/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> - <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Considera comunicacions i dades introduïdes per millorar sugger."</string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> + <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Considera comunicacions i dades introd. per millorar suggeriments"</string> </resources> diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml index 7137aa59c..5afaca093 100644 --- a/java/res/values-ca/strings.xml +++ b/java/res/values-ca/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecció d\'un fitxer de diccionari per instal·lar"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Realment vols instal·lar aquest fitxer per a <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"S\'ha produït un error"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Esborrar el diccionari de contactes"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Genera el diccionari de contactes"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Esborrar el diccionari personal"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Esborrar dicc. d\'histor. d\'usuaris"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Esborrar diccionari de personalitz."</string> diff --git a/java/res/values-cs/strings-config-important-notice.xml b/java/res/values-cs/strings-config-important-notice.xml index bb2f03abc..f69e94642 100644 --- a/java/res/values-cs/strings-config-important-notice.xml +++ b/java/res/values-cs/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Zlepšovat návrhy na základě vaší komunikace a zadaných dat"</string> </resources> diff --git a/java/res/values-da/strings-config-important-notice.xml b/java/res/values-da/strings-config-important-notice.xml index 57d32cd74..a167b3145 100644 --- a/java/res/values-da/strings-config-important-notice.xml +++ b/java/res/values-da/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Giv bedre forslag ud fra tidligere kommunikation og data"</string> </resources> diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index babea965c..7c0af04db 100644 --- a/java/res/values-da/strings.xml +++ b/java/res/values-da/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Vælg den ordbog, som du vil installere"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vil du virkelig installere denne fil for <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Der opstod en fejl"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Eksportér ordbog for kontakter"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Eksportér personlig ordbog"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Eksportér ordbog for brugerhistorik"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Eksportér ordbog for tilpasning"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Gem ordbog for kontakter"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Gem personlig ordbog"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Gem ordbog for brugerhistorik"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Gem ordbog for tilpasning"</string> <string name="button_default" msgid="3988017840431881491">"Standard"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Velkommen til <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"med glidende indtastning"</string> diff --git a/java/res/values-de/strings-config-important-notice.xml b/java/res/values-de/strings-config-important-notice.xml index 5a8420229..6734a1ce3 100644 --- a/java/res/values-de/strings-config-important-notice.xml +++ b/java/res/values-de/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Vorschläge anhand bisheriger Nachrichten und Eingaben verbessern"</string> </resources> diff --git a/java/res/values-el/strings-config-important-notice.xml b/java/res/values-el/strings-config-important-notice.xml index 4ee3532c8..3e0c45bc8 100644 --- a/java/res/values-el/strings-config-important-notice.xml +++ b/java/res/values-el/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Χρήση επικοινωνιών/δεδομένων πληκτρολόγησης για βελτίωση προτάσεων"</string> </resources> diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml index 5e888e0fd..4ea576ce1 100644 --- a/java/res/values-el/strings.xml +++ b/java/res/values-el/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Επιλογή αρχείου λεξικού για εγκατάσταση"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Εγκατάσταση αυτού του αρχείου για τα <xliff:g id="LANGUAGE_NAME">%s</xliff:g>;"</string> <string name="error" msgid="8940763624668513648">"Παρουσιάστηκε σφάλμα."</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Αποτύπωση λεξικού επαφών"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Εξαγωγή λεξικού επαφών"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Αποτύπωση προσωπικού λεξικού"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Αποτύπωση λεξικού ιστορικού χρήστη"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Αποτύπωση λεξικού εξατομίκευσης"</string> diff --git a/java/res/values-en-rGB/strings-config-important-notice.xml b/java/res/values-en-rGB/strings-config-important-notice.xml index a7ae30062..5530dbefc 100644 --- a/java/res/values-en-rGB/strings-config-important-notice.xml +++ b/java/res/values-en-rGB/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Learn from your communications and typed data to improve suggestions"</string> </resources> diff --git a/java/res/values-en-rIN/strings-config-important-notice.xml b/java/res/values-en-rIN/strings-config-important-notice.xml index a7ae30062..5530dbefc 100644 --- a/java/res/values-en-rIN/strings-config-important-notice.xml +++ b/java/res/values-en-rIN/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Learn from your communications and typed data to improve suggestions"</string> </resources> diff --git a/java/res/values-es-rUS/strings-config-important-notice.xml b/java/res/values-es-rUS/strings-config-important-notice.xml index b39cfbabf..4561842f0 100644 --- a/java/res/values-es-rUS/strings-config-important-notice.xml +++ b/java/res/values-es-rUS/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Aprende de mensajes y datos ingresados para mejorar las sugerencias."</string> </resources> diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml index c900c6aee..50583e8be 100644 --- a/java/res/values-es-rUS/strings.xml +++ b/java/res/values-es-rUS/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Seleccionar archivo de diccionario para instalar"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"¿Realmente quieres instalar este archivo para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Se produjo un error."</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Volcar diccionario de contactos"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Generar diccionario de contactos"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Volcar diccionario personal"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Volcar diccionario hist. usuario"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Volcar diccionario personalización"</string> diff --git a/java/res/values-es/strings-config-important-notice.xml b/java/res/values-es/strings-config-important-notice.xml index 4d82e8b37..1068ea88e 100644 --- a/java/res/values-es/strings-config-important-notice.xml +++ b/java/res/values-es/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Aprende de mensajes y datos escritos para mejorar sugerencias"</string> </resources> diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml index ad7547f70..3427751dc 100644 --- a/java/res/values-es/strings.xml +++ b/java/res/values-es/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecciona un archivo de diccionario para instalar"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"¿Seguro que quieres instalar este archivo para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Se ha producido un error"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Volcar diccionario de contactos"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Generar diccionario de contactos"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Volcar diccionario personal"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Volcar diccionario historial usuario"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Volcar diccionario personalización"</string> diff --git a/java/res/values-et-rEE/strings-config-important-notice.xml b/java/res/values-et-rEE/strings-config-important-notice.xml index c08d04576..d77b7f902 100644 --- a/java/res/values-et-rEE/strings-config-important-notice.xml +++ b/java/res/values-et-rEE/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Kommunikats. ja sisestatud andmetest õppimine soovit. täiustamiseks"</string> </resources> diff --git a/java/res/values-fa/strings-config-important-notice.xml b/java/res/values-fa/strings-config-important-notice.xml index b4e0335d7..915f3d4c6 100644 --- a/java/res/values-fa/strings-config-important-notice.xml +++ b/java/res/values-fa/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"یادگیری از ارتباطات و اطلاعات تایپ شده شما برای بهبود پیشنهادات"</string> </resources> diff --git a/java/res/values-fi/strings-config-important-notice.xml b/java/res/values-fi/strings-config-important-notice.xml index 2646501d5..316781bd5 100644 --- a/java/res/values-fi/strings-config-important-notice.xml +++ b/java/res/values-fi/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Ehdotusten parannus viestinnän ja kirjoitettujen tietojen avulla"</string> </resources> diff --git a/java/res/values-fr-rCA/strings-config-important-notice.xml b/java/res/values-fr-rCA/strings-config-important-notice.xml index 05b452c51..506101d8d 100644 --- a/java/res/values-fr-rCA/strings-config-important-notice.xml +++ b/java/res/values-fr-rCA/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Apprendre de vos communic. et données entrées pour amél. suggestions"</string> </resources> diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml index dcb1119c2..cb6daeeda 100644 --- a/java/res/values-fr-rCA/strings.xml +++ b/java/res/values-fr-rCA/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Sélectionner un fichier de dictionnaire à installer"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Installer ce fichier pour la langue « <xliff:g id="LANGUAGE_NAME">%s</xliff:g> »?"</string> <string name="error" msgid="8940763624668513648">"Une erreur s\'est produite"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Vider le dictionnaire des contacts"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Extraire dictionnaire des contacts"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Vider le dictionnaire personnel"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Vider dictionnaire hist. utilisateur"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Vider dictionnaire personnalisation"</string> diff --git a/java/res/values-fr/strings-config-important-notice.xml b/java/res/values-fr/strings-config-important-notice.xml index 21000de07..1672ee0f3 100644 --- a/java/res/values-fr/strings-config-important-notice.xml +++ b/java/res/values-fr/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Améliorer suggestions en fonction des messages et données saisies"</string> </resources> diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml index 3cd6e2696..e3243c3ed 100644 --- a/java/res/values-fr/strings.xml +++ b/java/res/values-fr/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Sélectionner un fichier de dictionnaire à installer"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Installer ce fichier pour la langue \"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>\" ?"</string> <string name="error" msgid="8940763624668513648">"Une erreur s\'est produite"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Supprimer dictionnaire des contacts"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Supprimer le dictionnaire personnel"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Supprimer l\'ancien dictionnaire"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Suppr. dictionnaire personnalisation"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Extraire dictionnaire des contacts"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Extraire le dictionnaire personnel"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Extraire dict. de l\'histor. util."</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Extraire dict. de personnalisation"</string> <string name="button_default" msgid="3988017840431881491">"Par défaut"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Bienvenue dans <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"avec la saisie gestuelle"</string> diff --git a/java/res/values-hi/strings-config-important-notice.xml b/java/res/values-hi/strings-config-important-notice.xml index 9a1c12b39..ae6b4c703 100644 --- a/java/res/values-hi/strings-config-important-notice.xml +++ b/java/res/values-hi/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"सुझावों में सुधार हेतु अपने संचार और लिखे गए डेटा से जानकारी पाएं"</string> </resources> diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml index 04879863f..b752d613a 100644 --- a/java/res/values-hi/strings.xml +++ b/java/res/values-hi/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"इंस्टॉल करने के लिए कोई शब्दकोश फ़ाइल चुनें"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"क्या वाकई <xliff:g id="LANGUAGE_NAME">%s</xliff:g> के लिए यह फ़ाइल इंस्टॉल करें?"</string> <string name="error" msgid="8940763624668513648">"कोई त्रुटि हुई थी"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"संपर्क शब्दकोश डंप करें"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"संपर्क शब्दकोश सूचीबद्ध करें"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"व्यक्तिगत शब्दकोश डंप करें"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"उपयोगकर्ता इतिहास शब्दकोश डंप करें"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"वैयक्तिकरण शब्दकोश डंप करें"</string> diff --git a/java/res/values-hr/strings-config-important-notice.xml b/java/res/values-hr/strings-config-important-notice.xml index c93544ed3..fff191bee 100644 --- a/java/res/values-hr/strings-config-important-notice.xml +++ b/java/res/values-hr/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Upotrijebi poruke i upisane podatke za poboljšanje prijedloga"</string> </resources> diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml index eb1391fe6..6d7e19120 100644 --- a/java/res/values-hr/strings.xml +++ b/java/res/values-hr/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Odabir datoteke rječnika za instaliranje"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Želite li zaista instalirati tu datoteku za <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Došlo je do pogreške"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Kopiranje rječnika kontakata"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Ispis rječnika kontakata"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Kopiranje osobnog rječnika"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Kopiranje rječ. povijesti korisnika"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Kopiranje rječnika za prilagodbu"</string> diff --git a/java/res/values-hu/strings-config-important-notice.xml b/java/res/values-hu/strings-config-important-notice.xml index b35c9f06c..4cb3c17ce 100644 --- a/java/res/values-hu/strings-config-important-notice.xml +++ b/java/res/values-hu/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Javaslatok javítása a kommunikáció és begépelt adatok alapján"</string> </resources> diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml index d4fffecf4..88fd3d6c3 100644 --- a/java/res/values-hu/strings.xml +++ b/java/res/values-hu/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Válasszon ki egy szótárfájlt a telepítéshez."</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Valóban telepíti ezt a fájlt <xliff:g id="LANGUAGE_NAME">%s</xliff:g> nyelvhez?"</string> <string name="error" msgid="8940763624668513648">"Hiba történt."</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Névjegyszótár törlése"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Névjegytár kiírása"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Személyes szótár törlése"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Felhasználóielőzmény-szótár törlése"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Testreszabási szótár törlése"</string> diff --git a/java/res/values-hy-rAM/strings-config-important-notice.xml b/java/res/values-hy-rAM/strings-config-important-notice.xml index 0d1588e13..2463c118f 100644 --- a/java/res/values-hy-rAM/strings-config-important-notice.xml +++ b/java/res/values-hy-rAM/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Բարելավեք առաջարկները` ձեր նամակագրությունից և մուտքագրած տվյալներից"</string> </resources> diff --git a/java/res/values-in/strings-config-important-notice.xml b/java/res/values-in/strings-config-important-notice.xml index c1950c41a..03ca54e02 100644 --- a/java/res/values-in/strings-config-important-notice.xml +++ b/java/res/values-in/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Belajar dari komunikasi & data terketik untuk meningkatkan saran"</string> </resources> diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml index b7907929e..9964daa89 100644 --- a/java/res/values-in/strings.xml +++ b/java/res/values-in/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pilih file kamus untuk dipasang"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Yakin ingin memasang file ini untuk <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Terjadi kesalahan"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Kosongkan kamus kontak"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Kosongkan kamus pribadi"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Kosongkan kamus riwayat pengguna"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Kosongkan kamus hasil personalisasi"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Buat daftar kamus kontak"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Buat daftar kamus pribadi"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Buat daftar kamus riwayat pengguna"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Buat daftar kamus personalisasi"</string> <string name="button_default" msgid="3988017840431881491">"Default"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Selamat datang di <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"dengan Ketikan Isyarat"</string> diff --git a/java/res/values-it/strings-config-important-notice.xml b/java/res/values-it/strings-config-important-notice.xml index deff79f89..95b2a1828 100644 --- a/java/res/values-it/strings-config-important-notice.xml +++ b/java/res/values-it/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Usa comunicazioni e dati digitati per migliorare i suggerimenti"</string> </resources> diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml index a9728f1de..78f398778 100644 --- a/java/res/values-it/strings.xml +++ b/java/res/values-it/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Seleziona un file di dizionario da installare"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vuoi davvero installare questo file per <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Si è verificato un errore"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Scarica dizionario contatti"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Scarica dizionario personale"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Scarica dizion. cronologia utente"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Scarica dizionario di personalizz."</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Estrai dizionario contatti"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Estrai dizionario personale"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Estrai dizion. cronologia utente"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Estrai dizionario di personalizz."</string> <string name="button_default" msgid="3988017840431881491">"Predefinito"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Benvenuto in <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"con la Digitazione gestuale"</string> diff --git a/java/res/values-iw/strings-config-important-notice.xml b/java/res/values-iw/strings-config-important-notice.xml index c7f352968..0ad8031f0 100644 --- a/java/res/values-iw/strings-config-important-notice.xml +++ b/java/res/values-iw/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"למד מהתכתבויות ומנתונים שהקלדת כדי לשפר את ההצעות"</string> </resources> diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml index 870623f93..accf80949 100644 --- a/java/res/values-iw/strings.xml +++ b/java/res/values-iw/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"בחירת קובץ מילון להתקנה"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"האם אתה באמת רוצה להתקין את הקובץ הזה עבור <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"אירעה שגיאה"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"מחק את מילון אנשי הקשר"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"צור מילון אנשי קשר"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"מחק מילון אישי"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"מחק את המילון של היסטוריית המשתמשים"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"מחק את מילון ההתאמה האישית"</string> diff --git a/java/res/values-ja/strings-config-important-notice.xml b/java/res/values-ja/strings-config-important-notice.xml index 937ddae5c..31b5a710f 100644 --- a/java/res/values-ja/strings-config-important-notice.xml +++ b/java/res/values-ja/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"メッセージなどのやり取りや入力したデータから入力候補を予測します"</string> </resources> diff --git a/java/res/values-ka-rGE/strings-config-important-notice.xml b/java/res/values-ka-rGE/strings-config-important-notice.xml index e43ca01b1..02b280cb1 100644 --- a/java/res/values-ka-rGE/strings-config-important-notice.xml +++ b/java/res/values-ka-rGE/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"უკეთესი შეთავაზებისთვის თქვენი კომუნიკაციიდან და ტექსტიდან სწავლა"</string> </resources> diff --git a/java/res/values-km-rKH/strings-config-important-notice.xml b/java/res/values-km-rKH/strings-config-important-notice.xml index ad0325adb..7f58d613b 100644 --- a/java/res/values-km-rKH/strings-config-important-notice.xml +++ b/java/res/values-km-rKH/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"សិក្សាការភ្ជាប់របស់អ្នកនិងទិន្នន័យដែលបានបញ្ចូលដើម្បីធ្វើសំណើឲ្យល្អ"</string> </resources> diff --git a/java/res/values-ko/strings-config-important-notice.xml b/java/res/values-ko/strings-config-important-notice.xml index 2ea6e49f4..b8cfb375d 100644 --- a/java/res/values-ko/strings-config-important-notice.xml +++ b/java/res/values-ko/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"사용자의 대화 내용과 입력한 데이터를 통해 단어 추천의 정확도를 개선합니다."</string> </resources> diff --git a/java/res/values-lo-rLA/strings-config-important-notice.xml b/java/res/values-lo-rLA/strings-config-important-notice.xml index d4e5052bd..079dd6b01 100644 --- a/java/res/values-lo-rLA/strings-config-important-notice.xml +++ b/java/res/values-lo-rLA/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"ຮຽນຮູ້ຈາກການສື່ສານ ແລະຂໍ້ມູນທີ່ທ່ານເຄີຍພິມເພື່ອປັບປຸງຄຳແນະນຳ"</string> </resources> diff --git a/java/res/values-lt/strings-config-important-notice.xml b/java/res/values-lt/strings-config-important-notice.xml index 633980ece..cb91b5be1 100644 --- a/java/res/values-lt/strings-config-important-notice.xml +++ b/java/res/values-lt/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Mokytis iš ryšių ir įvestų duomenų, siekiant pagerinti pasiūlymus"</string> </resources> diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml index 9efdc679c..331656fc9 100644 --- a/java/res/values-lt/strings.xml +++ b/java/res/values-lt/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pasirinkite diegiamą žodyno failą"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Ar tikrai įdiegti šį failą <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Įvyko klaida"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Iškelti kontaktų žodyną"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Sudaryti kontaktų žodyną"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Iškelti asmeninį žodyną"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Iškelti naudotojo istorijos žodyną"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Iškelti suasmeninimo žodyną"</string> diff --git a/java/res/values-lv/strings-config-important-notice.xml b/java/res/values-lv/strings-config-important-notice.xml index ce2062dd9..916128c5e 100644 --- a/java/res/values-lv/strings-config-important-notice.xml +++ b/java/res/values-lv/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Izmantojiet saziņu un ievadītos datus, lai uzlabotu ieteikumus."</string> </resources> diff --git a/java/res/values-mn-rMN/strings-config-important-notice.xml b/java/res/values-mn-rMN/strings-config-important-notice.xml index 047cfc7bf..fb07acecf 100644 --- a/java/res/values-mn-rMN/strings-config-important-notice.xml +++ b/java/res/values-mn-rMN/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Зөвлөмжүүдийг сайжруулахын тулд таны харилцсан, бичсэн зүйлсээс суралцана"</string> </resources> diff --git a/java/res/values-ms-rMY/strings-config-important-notice.xml b/java/res/values-ms-rMY/strings-config-important-notice.xml index e53ada237..f021fe6b6 100644 --- a/java/res/values-ms-rMY/strings-config-important-notice.xml +++ b/java/res/values-ms-rMY/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Perbaik cadangan berdasarkan komunikasi anda dan data yang ditaip"</string> </resources> diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml index 6fbd38c76..33ec0651e 100644 --- a/java/res/values-ms-rMY/strings.xml +++ b/java/res/values-ms-rMY/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pilih fail kamus untuk dipasang"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Betul-betul pasang fail ini untuk <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Berlaku ralat"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Buang kamus kenalan"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Buang kamus peribadi"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Buang kamus sejarah pengguna"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Buang kamus pemperibadian"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Longgokan kamus kenalan"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Longgokan kamus peribadi"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Longgokan kamus sejarah pengguna"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Longgokan kamus pemperibadian"</string> <string name="button_default" msgid="3988017840431881491">"Lalai"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Selamat datang ke <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"dengan Taipan Gerak Isyarat"</string> diff --git a/java/res/values-nb/strings-config-important-notice.xml b/java/res/values-nb/strings-config-important-notice.xml index 8c79eef0b..f64f41538 100644 --- a/java/res/values-nb/strings-config-important-notice.xml +++ b/java/res/values-nb/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Bruk kommunikasjonen og inndataene dine for å få bedre forslag"</string> </resources> diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index 02f13bb41..6a4eaf422 100644 --- a/java/res/values-nb/strings.xml +++ b/java/res/values-nb/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Velg ordboksfilen du vil installere"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vil du virkelig installere denne filen for <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Det oppsto en feil"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Tøm kontakter-ordlisten"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Generer ordliste for kontakter"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Tøm den personlige ordlisten"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Tøm brukerlogg-ordlisten"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Tøm tilpasningsordlisten"</string> diff --git a/java/res/values-ne-rNP/strings-config-important-notice.xml b/java/res/values-ne-rNP/strings-config-important-notice.xml index 6945a61cb..71c016ac9 100644 --- a/java/res/values-ne-rNP/strings-config-important-notice.xml +++ b/java/res/values-ne-rNP/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"सुझावहरू सुधार गर्न सञ्चारहरू र टाइप गरिएको डेटाबाट जान्नुहोस्"</string> </resources> diff --git a/java/res/values-nl/strings-config-important-notice.xml b/java/res/values-nl/strings-config-important-notice.xml index f77a1f45a..096e029da 100644 --- a/java/res/values-nl/strings-config-important-notice.xml +++ b/java/res/values-nl/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Suggesties verbeteren met uw communicatie en getypte gegevens"</string> </resources> diff --git a/java/res/values-pl/strings-config-important-notice.xml b/java/res/values-pl/strings-config-important-notice.xml index 03da01d87..8a78ab0df 100644 --- a/java/res/values-pl/strings-config-important-notice.xml +++ b/java/res/values-pl/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Analizuj wiadomości i wpisywane dane, by ulepszać podpowiedzi"</string> </resources> diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml index 9d46f61fe..a4a6931c3 100644 --- a/java/res/values-pl/strings.xml +++ b/java/res/values-pl/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Wybierz plik słownika do zainstalowania"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Czy na pewno zainstalować ten plik dla języka: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Wystąpił błąd"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Zrzut słownika kontaktów"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Zrzut słownika osobistego"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Zrzut słownika historii użytkownika"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Zrzut słownika personalizacji"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Wyciąg ze słownika kontaktów"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Wyciąg ze słownika osobistego"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Wyciąg ze słownika historii użytk."</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Wyciąg ze słownika personalizacji"</string> <string name="button_default" msgid="3988017840431881491">"Domyślne"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Witamy w aplikacji <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"z pisaniem gestami"</string> diff --git a/java/res/values-pt-rPT/strings-config-important-notice.xml b/java/res/values-pt-rPT/strings-config-important-notice.xml index 0724173b4..7cc395917 100644 --- a/java/res/values-pt-rPT/strings-config-important-notice.xml +++ b/java/res/values-pt-rPT/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Aprender com comunicações e dados introd. para melhorar sugestões"</string> </resources> diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml index 8adaa4dde..4311dcd0b 100644 --- a/java/res/values-pt-rPT/strings.xml +++ b/java/res/values-pt-rPT/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecione um ficheiro de dicionário para instalar"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Instalar mesmo este ficheiro para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Ocorreu um erro"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Descarregar dicionário de contactos"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Transferir dicionário de contactos"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Descarregar dicionário pessoal"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Desc. dicion. do hist. do utiliz."</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Descarregar dicionário de personal."</string> diff --git a/java/res/values-pt/strings-config-important-notice.xml b/java/res/values-pt/strings-config-important-notice.xml index 041a04c26..05fe4d126 100644 --- a/java/res/values-pt/strings-config-important-notice.xml +++ b/java/res/values-pt/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Aprender com mensagens e dados digitados para melhorar sugestões"</string> </resources> diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml index 966c4021b..5bbab4621 100644 --- a/java/res/values-pt/strings.xml +++ b/java/res/values-pt/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecione um arquivo de dicionário para instalar"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Deseja instalar este arquivo para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Ocorreu um erro"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Despejar dicionário de contatos"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Listar dicionário de contatos"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Despejar dicionário pessoal"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Despejar dicio. de hist. do usuário"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Despejar dicion. de personalização"</string> diff --git a/java/res/values-ro/strings-config-important-notice.xml b/java/res/values-ro/strings-config-important-notice.xml index ff064577e..2de8dde45 100644 --- a/java/res/values-ro/strings-config-important-notice.xml +++ b/java/res/values-ro/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> - <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Utilizați mesajele și datele introduse pt. a îmbunătăți sugestiile"</string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> + <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Utilizează mesajele și datele introduse pt. a îmbunătăți sugestiile"</string> </resources> diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml index ac713d996..b9c89773d 100644 --- a/java/res/values-ro/strings.xml +++ b/java/res/values-ro/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selectați un fișier dicționar de instalat"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Doriți să instalați acest fișier pentru <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"A apărut o eroare"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Eliminați dicționar pers. cont."</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Eliminați dicționar personal"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Eliminați dicționar istoric utiliz."</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Eliminați dicționar personalizare"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Listați dicționar persoane contact"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Listați dicționar personal"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Listați dicționar istoric utilizator"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Listați dicționar personalizare"</string> <string name="button_default" msgid="3988017840431881491">"Prestabilit"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Bun venit la <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"cu Tastarea gestuală"</string> diff --git a/java/res/values-ru/strings-config-important-notice.xml b/java/res/values-ru/strings-config-important-notice.xml index b2f215c4b..33828047c 100644 --- a/java/res/values-ru/strings-config-important-notice.xml +++ b/java/res/values-ru/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Устройство будет запоминать то, что вы вводите чаще всего"</string> </resources> diff --git a/java/res/values-sk/strings-config-important-notice.xml b/java/res/values-sk/strings-config-important-notice.xml index 00365ab07..4adb406c0 100644 --- a/java/res/values-sk/strings-config-important-notice.xml +++ b/java/res/values-sk/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Zlepšovať návrhy na základe komunikácie a zadaných údajov"</string> </resources> diff --git a/java/res/values-sl/strings-config-important-notice.xml b/java/res/values-sl/strings-config-important-notice.xml index fd14a6a52..29c5351a4 100644 --- a/java/res/values-sl/strings-config-important-notice.xml +++ b/java/res/values-sl/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Vaša sporočila in vnesene podatke uporabi za boljše predloge"</string> </resources> diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml index 650b69f5f..3dabb7e3e 100644 --- a/java/res/values-sl/strings.xml +++ b/java/res/values-sl/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Izberite datoteko slovarja, ki jo želite namestiti"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Zares želite namestiti to datoteko za ta jezik: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Prišlo je do napake"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Izvoz slovarja stikov"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Izpis slovarja stikov"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Izvoz osebnega slovarja"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Izvoz slovarja zgodovine uporabnika"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Izvoz slovarja za prilagajanje"</string> diff --git a/java/res/values-sr/strings-config-important-notice.xml b/java/res/values-sr/strings-config-important-notice.xml index a6eb25ed9..e226a06ee 100644 --- a/java/res/values-sr/strings-config-important-notice.xml +++ b/java/res/values-sr/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Користи комуникације и унете податке ради побољшања предлога"</string> </resources> diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml index 782830d6f..af8760fd8 100644 --- a/java/res/values-sr/strings.xml +++ b/java/res/values-sr/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Избор датотеке речника за инсталирање"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Желите ли стварно да инсталирате ову датотеку за <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Дошло је до грешке"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Избриши речник контаката"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Избриши лични речник"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Избриши речник историје корисника"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Избриши персонализовани речник"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Направи сирову копију речника контаката"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Направи сирову копију личног речника"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Направи сирову копију речника историје корисника"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Направи сирову копију персонализованог речника"</string> <string name="button_default" msgid="3988017840431881491">"Подразумевано"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Добро дошли у <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"помоћу Куцања покретима"</string> diff --git a/java/res/values-sv/strings-config-important-notice.xml b/java/res/values-sv/strings-config-important-notice.xml index 8d8a08934..d484d6766 100644 --- a/java/res/values-sv/strings-config-important-notice.xml +++ b/java/res/values-sv/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Få bättre förslag genom att använda tidigare angiven data och annan kommunikation"</string> </resources> diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index 22a5ce3ef..cda89b827 100644 --- a/java/res/values-sv/strings.xml +++ b/java/res/values-sv/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Välj en ordboksfil att installera"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vill du verkligen installera filen för <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Ett fel uppstod"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Dumpa ordlista för kontakter"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Ta fram ordlista för kontakter"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Dumpa personlig ordlista"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Dumpa ordlista för användarhistorik"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Dumpa anpassad ordlista"</string> diff --git a/java/res/values-sw/strings-config-important-notice.xml b/java/res/values-sw/strings-config-important-notice.xml index 10eab64cd..8a74bdd8c 100644 --- a/java/res/values-sw/strings-config-important-notice.xml +++ b/java/res/values-sw/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Jifunze kutoka kwenye mawasiliano yako na data iliyocharazwa ili kuboresha mapendekezo"</string> </resources> diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml index 50c6aaa38..587e95ad2 100644 --- a/java/res/values-sw/strings.xml +++ b/java/res/values-sw/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Chagua faili ya kamusi ya kusakinisha"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Ungependa kusakinisha faili hii ya <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Kulikuwa na hitilafu"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Tupa kamusi ya anwani"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Onyesha orodha ya anwani"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Tupa kamusi ya kibinafsi"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Tupa kamusi ya historia ya mtumiaji"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Tupa kamusi ya kuwekewa mapendeleo"</string> diff --git a/java/res/values-th/strings-config-important-notice.xml b/java/res/values-th/strings-config-important-notice.xml index 78342ae70..e156d5f23 100644 --- a/java/res/values-th/strings-config-important-notice.xml +++ b/java/res/values-th/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"เรียนรู้จากการสื่อสารและข้อมูลที่พิมพ์ของคุณเพื่อปรับปรุงคำแนะนำ"</string> </resources> diff --git a/java/res/values-tl/strings-config-important-notice.xml b/java/res/values-tl/strings-config-important-notice.xml index 687f8610f..5e0c0b32a 100644 --- a/java/res/values-tl/strings-config-important-notice.xml +++ b/java/res/values-tl/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Pahusayin ang suhestiyon batay sa iyong pag-uusap at na-type na data"</string> </resources> diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml index ac3cb1c0e..c0503a32b 100644 --- a/java/res/values-tl/strings.xml +++ b/java/res/values-tl/strings.xml @@ -167,14 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pumili ng file ng diksyunaryo na ii-install"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Talagang ii-install ang file na ito para sa <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Nagkaroon ng error"</string> - <!-- no translation found for prefs_dump_contacts_dict (7227327764402323097) --> - <skip /> - <!-- no translation found for prefs_dump_user_dict (294870685041741951) --> - <skip /> - <!-- no translation found for prefs_dump_user_history_dict (6821075152449554628) --> - <skip /> - <!-- no translation found for prefs_dump_personalization_dict (7558387996151745284) --> - <skip /> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Diksyunaryo ng contacts ng Dump"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Personal na diksyunaryo ng Dump"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Diksyunaryo ng user history ng Dump"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Personalization dictionary ng Dump"</string> <string name="button_default" msgid="3988017840431881491">"Default"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Maligayang pagdating sa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"gamit ang Gesture na Pag-type"</string> diff --git a/java/res/values-tr/strings-config-important-notice.xml b/java/res/values-tr/strings-config-important-notice.xml index 06c837871..28e333d46 100644 --- a/java/res/values-tr/strings-config-important-notice.xml +++ b/java/res/values-tr/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> - <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Önerileri iyileştirmek için iletişimlerimden ve yazılan verilerden öğren"</string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> + <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Önerileri iyileştirmek için iletşmlrmdn. ve yazılan verilerden öğren"</string> </resources> diff --git a/java/res/values-uk/strings-config-important-notice.xml b/java/res/values-uk/strings-config-important-notice.xml index 3d6a4e759..6172b34e6 100644 --- a/java/res/values-uk/strings-config-important-notice.xml +++ b/java/res/values-uk/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Пристрій буде запам’ятовувати, що ви пишете, надсилаєте й отримуєте"</string> </resources> diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml index 1ed94ad7a..ee9208ce1 100644 --- a/java/res/values-uk/strings.xml +++ b/java/res/values-uk/strings.xml @@ -167,10 +167,10 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Вибрати файл словника, який потрібно встановити"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Справді встановити цей файл для такої мови: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Сталася помилка"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Дамп словника контактів"</string> - <string name="prefs_dump_user_dict" msgid="294870685041741951">"Дамп особистого словника"</string> - <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Дамп словника історії користувача"</string> - <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Дамп словника персоналізації"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Вивантаження словника контактів"</string> + <string name="prefs_dump_user_dict" msgid="294870685041741951">"Вивантаження особистого словника"</string> + <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Вивантаж. словника користув. історії"</string> + <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Вивантаження словника персоналізації"</string> <string name="button_default" msgid="3988017840431881491">"За умовчанням"</string> <string name="setup_welcome_title" msgid="6112821709832031715">"Вітаємо в програмі <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="setup_welcome_additional_description" msgid="8150252008545768953">"з функцією Ввід жестами"</string> diff --git a/java/res/values-vi/strings-config-important-notice.xml b/java/res/values-vi/strings-config-important-notice.xml index 6528f06ed..b753e18f4 100644 --- a/java/res/values-vi/strings-config-important-notice.xml +++ b/java/res/values-vi/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Tìm hiểu từ thư từ trao đổi và dữ liệu đã nhập của bạn để cải tiến đề xuất"</string> </resources> diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml index c0ccc7c52..112bc4785 100644 --- a/java/res/values-vi/strings.xml +++ b/java/res/values-vi/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Chọn tệp từ điển để cài đặt"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Thực sự cài đặt tệp này cho <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Đã xảy ra lỗi"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Lưu vào từ điển danh bạ"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Tạo từ điển danh bạ"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Lưu vào từ điển cá nhân"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Lưu vào từ điển lịch sử người dùng"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Lưu vào từ điển cá nhân hóa"</string> diff --git a/java/res/values-zh-rCN/strings-config-important-notice.xml b/java/res/values-zh-rCN/strings-config-important-notice.xml index 2ffe7d953..2394e31a8 100644 --- a/java/res/values-zh-rCN/strings-config-important-notice.xml +++ b/java/res/values-zh-rCN/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"根据您的通信记录和以往输入的数据来完善建议"</string> </resources> diff --git a/java/res/values-zh-rHK/strings-config-important-notice.xml b/java/res/values-zh-rHK/strings-config-important-notice.xml index 9e80655a3..3784c7667 100644 --- a/java/res/values-zh-rHK/strings-config-important-notice.xml +++ b/java/res/values-zh-rHK/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"根據您的通訊記錄和已輸入的資料改善建議"</string> </resources> diff --git a/java/res/values-zh-rTW/strings-config-important-notice.xml b/java/res/values-zh-rTW/strings-config-important-notice.xml index f1bdc7774..692d61cb3 100644 --- a/java/res/values-zh-rTW/strings-config-important-notice.xml +++ b/java/res/values-zh-rTW/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"根據您的通訊紀錄和以往輸入的資料改善建議項目"</string> </resources> diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml index 8a56f2810..1fdf7e830 100644 --- a/java/res/values-zh-rTW/strings.xml +++ b/java/res/values-zh-rTW/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"選取要安裝的字典檔案"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"確定要安裝這個<xliff:g id="LANGUAGE_NAME">%s</xliff:g>檔案嗎?"</string> <string name="error" msgid="8940763624668513648">"發生錯誤"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"捨棄聯絡人字典"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"傾印聯絡人字典"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"捨棄個人字典"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"捨棄使用者紀錄字典"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"捨棄個人化字典"</string> diff --git a/java/res/values-zu/strings-config-important-notice.xml b/java/res/values-zu/strings-config-important-notice.xml index 95d5a290c..245b05690 100644 --- a/java/res/values-zu/strings-config-important-notice.xml +++ b/java/res/values-zu/strings-config-important-notice.xml @@ -20,7 +20,9 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="important_notice_title" msgid="1836002733109536160"></string> - <string name="important_notice_contents" msgid="897137043719116217"></string> + <string-array name="important_notice_title_array"> + </string-array> + <string-array name="important_notice_contents_array"> + </string-array> <string name="use_personalized_dicts_summary" msgid="590432261305469627">"Funda kusukela kwezokuxhumana zakho nedatha ethayiphiwe ukuze uthuthukise iziphakamiso"</string> </resources> diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml index 42430ba27..f4c0d9255 100644 --- a/java/res/values-zu/strings.xml +++ b/java/res/values-zu/strings.xml @@ -167,7 +167,7 @@ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Khetha ifayela lesichazamazwi ukuze ulifake"</string> <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Fakela ngempela leli fayela i-<xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string> <string name="error" msgid="8940763624668513648">"Kube nephutha"</string> - <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Lahla isichazamazwi soxhumana nabo"</string> + <string name="prefs_dump_contacts_dict" msgid="7227327764402323097">"Yenza uhlu isichazamazwi soxhumana nabo"</string> <string name="prefs_dump_user_dict" msgid="294870685041741951">"Lahla isichazamazwi somuntu siqu"</string> <string name="prefs_dump_user_history_dict" msgid="6821075152449554628">"Lahla isichazamazwi somlando womsebenzisi"</string> <string name="prefs_dump_personalization_dict" msgid="7558387996151745284">"Lahla isichazamazwi sokwenza kube ngokwakho"</string> diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index 055060642..475e92f2e 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -175,7 +175,7 @@ </declare-styleable> <declare-styleable name="SuggestionStripView"> - <attr name="suggestionStripOption" format="integer"> + <attr name="suggestionStripOptions" format="integer"> <!-- This should be aligned with SuggestionStripLayoutHelper.AUTO_CORRECT_* and etc. --> <flag name="autoCorrectBold" value="0x01" /> <flag name="autoCorrectUnderline" value="0x02" /> diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml index 93f25a7f6..517174495 100644 --- a/java/res/values/colors.xml +++ b/java/res/values/colors.xml @@ -39,6 +39,7 @@ <color name="typed_word_color_ics">#D833B5E5</color> <color name="suggested_word_color_ics">#B233B5E5</color> <color name="highlight_translucent_color_ics">#9933B5E5</color> + <color name="key_text_color_holo">@android:color/white</color> <color name="key_text_shadow_color_holo">@android:color/transparent</color> <color name="key_text_inactivated_color_holo">#66E0E4E5</color> <color name="key_hint_letter_color_holo">#80000000</color> @@ -65,7 +66,4 @@ <!-- TODO: Color which should be included in the theme --> <color name="emoji_key_background_color">#00000000</color> <color name="emoji_key_pressed_background_color">#30FFFFFF</color> - - <color name="key_text_color_normal_holo">@android:color/white</color> - <color name="key_text_color_functional_holo">@android:color/white</color> </resources> diff --git a/java/res/values/themes-gb.xml b/java/res/values/themes-gb.xml index a460d4f7f..c189da383 100644 --- a/java/res/values/themes-gb.xml +++ b/java/res/values/themes-gb.xml @@ -133,7 +133,7 @@ parent="SuggestionStripView" > <item name="android:background">@drawable/keyboard_suggest_strip_gb</item> - <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item> + <item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item> <item name="colorValidTypedWord">@color/highlight_color_gb</item> <item name="colorTypedWord">@color/typed_word_color_gb</item> <item name="colorAutoCorrect">@color/highlight_color_gb</item> diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml index caea92186..720eda9ce 100644 --- a/java/res/values/themes-ics.xml +++ b/java/res/values/themes-ics.xml @@ -112,7 +112,7 @@ parent="SuggestionStripView" > <item name="android:background">@drawable/keyboard_suggest_strip_holo</item> - <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item> + <item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item> <item name="colorValidTypedWord">@color/typed_word_color_ics</item> <item name="colorTypedWord">@color/typed_word_color_ics</item> <item name="colorAutoCorrect">@color/highlight_color_ics</item> diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml index 0599fb65e..830527171 100644 --- a/java/res/values/themes-klp.xml +++ b/java/res/values/themes-klp.xml @@ -112,7 +112,7 @@ parent="SuggestionStripView" > <item name="android:background">@drawable/keyboard_suggest_strip_holo</item> - <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item> + <item name="suggestionStripOptions">autoCorrectBold|validTypedWordBold</item> <item name="colorValidTypedWord">@color/typed_word_color_klp</item> <item name="colorTypedWord">@color/typed_word_color_klp</item> <item name="colorAutoCorrect">@color/highlight_color_klp</item> diff --git a/java/res/xml/row_pcqwerty5.xml b/java/res/xml/row_pcqwerty5.xml index a72f38880..f6438ab0f 100644 --- a/java/res/xml/row_pcqwerty5.xml +++ b/java/res/xml/row_pcqwerty5.xml @@ -64,18 +64,8 @@ latin:keyStyle="defaultEnterKeyStyle" latin:keySpec="!icon/enter_key|!code/key_enter" latin:keyWidth="15.384%p" /> - <switch> - <case - latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted" - > - <Spacer /> - </case> - <!-- keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted" --> - <default> - <Key - latin:keyStyle="emojiKeyStyle" - latin:keyWidth="fillRight" /> - </default> - </switch> + <Key + latin:keyStyle="emojiKeyStyle" + latin:keyWidth="fillRight" /> </Row> </merge> diff --git a/java/res/xml/rowkeys_symbols_shift1.xml b/java/res/xml/rowkeys_symbols_shift1.xml index 7cb3213f0..4c2722c7e 100644 --- a/java/res/xml/rowkeys_symbols_shift1.xml +++ b/java/res/xml/rowkeys_symbols_shift1.xml @@ -34,11 +34,11 @@ <!-- U+221A: "√" SQUARE ROOT --> <Key latin:keySpec="√" /> - <!-- U+03A0: "Π" GREEK CAPITAL LETTER PI - U+03C0: "π" GREEK SMALL LETTER PI --> + <!-- U+03C0: "π" GREEK SMALL LETTER PI + U+03A0: "Π" GREEK CAPITAL LETTER PI --> <Key - latin:keySpec="Π" - latin:moreKeys="π" /> + latin:keySpec="π" + latin:moreKeys="Π" /> <!-- U+00F7: "÷" DIVISION SIGN --> <Key latin:keySpec="÷" /> diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java index 4c53b528f..7fff46aaf 100644 --- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java @@ -25,7 +25,6 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; -import android.graphics.Typeface; import android.os.Build; import android.os.CountDownTimer; import android.preference.PreferenceManager; @@ -49,6 +48,8 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard; import com.android.inputmethod.keyboard.internal.EmojiLayoutParams; import com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView; +import com.android.inputmethod.keyboard.internal.KeyDrawParams; +import com.android.inputmethod.keyboard.internal.KeyVisualAttributes; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; @@ -634,20 +635,23 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange // TODO: } - // Hack: These parameters are hacky. - public void startEmojiPalettes(final String switchToAlphaLabel, final int switchToAlphaColor, - final float switchToAlphaSize, final Typeface switchToAlphaTypeface) { + private static void setupAlphabetKey(final TextView alphabetKey, final String label, + final KeyDrawParams params) { + alphabetKey.setText(label); + alphabetKey.setTextColor(params.mTextColor); + alphabetKey.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mLabelSize); + alphabetKey.setTypeface(params.mTypeface); + } + + public void startEmojiPalettes(final String switchToAlphaLabel, + final KeyVisualAttributes keyVisualAttr) { if (DEBUG_PAGER) { Log.d(TAG, "allocate emoji palettes memory " + mCurrentPagerPosition); } - mAlphabetKeyLeft.setText(switchToAlphaLabel); - mAlphabetKeyLeft.setTextColor(switchToAlphaColor); - mAlphabetKeyLeft.setTextSize(TypedValue.COMPLEX_UNIT_PX, switchToAlphaSize); - mAlphabetKeyLeft.setTypeface(switchToAlphaTypeface); - mAlphabetKeyRight.setText(switchToAlphaLabel); - mAlphabetKeyRight.setTextColor(switchToAlphaColor); - mAlphabetKeyRight.setTextSize(TypedValue.COMPLEX_UNIT_PX, switchToAlphaSize); - mAlphabetKeyRight.setTypeface(switchToAlphaTypeface); + final KeyDrawParams params = new KeyDrawParams(); + params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr); + setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params); + setupAlphabetKey(mAlphabetKeyRight, switchToAlphaLabel, params); mEmojiPager.setAdapter(mEmojiPalettesAdapter); mEmojiPager.setCurrentItem(mCurrentPagerPosition); } diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index ceda9ee9a..816a94300 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -137,8 +137,6 @@ public class Key implements Comparable<Key> { private final OptionalAttributes mOptionalAttributes; - private static final int DEFAULT_TEXT_COLOR = 0xFFFFFFFF; - private static final class OptionalAttributes { /** Text to output when pressed. This can be multiple characters, like ".com" */ public final String mOutputText; @@ -585,22 +583,7 @@ public class Key implements Comparable<Key> { } public final int selectTextColor(final KeyDrawParams params) { - if (isShiftedLetterActivated()) { - return params.mTextInactivatedColor; - } - if (params.mTextColorStateList == null) { - return DEFAULT_TEXT_COLOR; - } - final int[] state; - // TODO: Hack!!!!!!!! Consider having a new attribute for the functional text labels. - // Currently, we distinguish "input key" from "functional key" by checking the - // length of the label( > 1) and "functional" attributes (= true). - if (mLabel != null && mLabel.length() > 1) { - state = getCurrentDrawableState(); - } else { - state = KEY_STATE_NORMAL; - } - return params.mTextColorStateList.getColorForState(state, DEFAULT_TEXT_COLOR); + return isShiftedLetterActivated() ? params.mTextInactivatedColor : params.mTextColor; } public final int selectHintTextSize(final KeyDrawParams params) { @@ -733,10 +716,14 @@ public class Key implements Comparable<Key> { return (attrs != null) ? attrs.mAltCode : CODE_UNSPECIFIED; } + public int getIconId() { + return mIconId; + } + public Drawable getIcon(final KeyboardIconsSet iconSet, final int alpha) { final OptionalAttributes attrs = mOptionalAttributes; final int disabledIconId = (attrs != null) ? attrs.mDisabledIconId : ICON_UNDEFINED; - final int iconId = mEnabled ? mIconId : disabledIconId; + final int iconId = mEnabled ? getIconId() : disabledIconId; final Drawable icon = iconSet.getIconDrawable(iconId); if (icon != null) { icon.setAlpha(alpha); @@ -748,7 +735,7 @@ public class Key implements Comparable<Key> { final OptionalAttributes attrs = mOptionalAttributes; final int previewIconId = (attrs != null) ? attrs.mPreviewIconId : ICON_UNDEFINED; return previewIconId != ICON_UNDEFINED - ? iconSet.getIconDrawable(previewIconId) : iconSet.getIconDrawable(mIconId); + ? iconSet.getIconDrawable(previewIconId) : iconSet.getIconDrawable(getIconId()); } public int getWidth() { diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index 03d9defa0..87368d4ef 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -86,6 +86,9 @@ public class KeyDetector { * @return the key that the touch point hits. */ public Key detectHitKey(final int x, final int y) { + if (mKeyboard == null) { + return null; + } final int touchX = getTouchX(x); final int touchY = getTouchY(y); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 6215e2710..2711d249b 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -19,7 +19,6 @@ package com.android.inputmethod.keyboard; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; -import android.graphics.Paint; import android.preference.PreferenceManager; import android.util.Log; import android.view.ContextThemeWrapper; @@ -31,7 +30,7 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.compat.InputMethodServiceCompatUtils; import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException; import com.android.inputmethod.keyboard.internal.KeyboardState; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.keyboard.internal.KeyboardTextsSet; import com.android.inputmethod.latin.InputView; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; @@ -46,7 +45,7 @@ import com.android.inputmethod.latin.utils.ResourceUtils; public final class KeyboardSwitcher implements KeyboardState.SwitchActions { private static final String TAG = KeyboardSwitcher.class.getSimpleName(); - static final class KeyboardTheme { + public static final class KeyboardTheme { public final int mThemeId; public final int mStyleId; @@ -81,8 +80,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { private KeyboardState mState; private KeyboardLayoutSet mKeyboardLayoutSet; + // TODO: The following {@link KeyboardTextsSet} should be in {@link KeyboardLayoutSet}. + private final KeyboardTextsSet mKeyboardTextsSet = new KeyboardTextsSet(); private SettingsValues mCurrentSettingsValues; - private Key mSwitchToAlphaKey; /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of * what user actually typed. */ @@ -163,8 +163,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mCurrentSettingsValues = settingsValues; try { mState.onLoadKeyboard(); - final Keyboard symbols = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS); - mSwitchToAlphaKey = symbols.getKey(Constants.CODE_SWITCH_ALPHA_SYMBOL); + mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale()); } catch (KeyboardLayoutSetException e) { Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause()); LatinImeLogger.logOnException(e.mKeyboardId.toString(), e.getCause()); @@ -290,10 +289,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { @Override public void setEmojiKeyboard() { mMainKeyboardFrame.setVisibility(View.GONE); - final Paint paint = mKeyboardView.newLabelPaint(mSwitchToAlphaKey); mEmojiPalettesView.startEmojiPalettes( - mSwitchToAlphaKey.getLabel(), paint.getColor(), paint.getTextSize(), - paint.getTypeface()); + mKeyboardTextsSet.getText(KeyboardTextsSet.SWITCH_TO_ALPHA_KEY_LABEL), + mKeyboardView.getKeyVisualAttribute()); mEmojiPalettesView.setVisibility(View.VISIBLE); } @@ -342,10 +340,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mState.onCodeInput(code, mLatinIME.getCurrentAutoCapsState()); } - private boolean isShowingMainKeyboard() { - return null != mKeyboardView && mKeyboardView.isShown(); - } - public boolean isShowingEmojiPalettes() { return mEmojiPalettesView != null && mEmojiPalettesView.isShown(); } @@ -378,10 +372,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } } - public boolean isShowingMainKeyboardOrEmojiPalettes() { - return isShowingMainKeyboard() || isShowingEmojiPalettes(); - } - public View onCreateInputView(final boolean isHardwareAcceleratedDrawingEnabled) { if (mKeyboardView != null) { mKeyboardView.closing(); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index dd3ab9cce..18e51d392 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -146,6 +146,10 @@ public class KeyboardView extends View { mPaint.setAntiAlias(true); } + public KeyVisualAttributes getKeyVisualAttribute() { + return mKeyVisualAttributes; + } + private static void blendAlpha(final Paint paint, final int alpha) { final int color = paint.getColor(); paint.setARGB((paint.getAlpha() * alpha) / Constants.Color.ALPHA_OPAQUE, diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java index 12e063261..d57ea5a94 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java +++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java @@ -73,9 +73,13 @@ public class EmojiLayoutParams { ll.setLayoutParams(lp); } + public int getActionBarHeight() { + return mEmojiActionBarHeight - mBottomPadding; + } + public void setActionBarProperties(final LinearLayout ll) { final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams(); - lp.height = mEmojiActionBarHeight - mBottomPadding; + lp.height = getActionBarHeight(); ll.setLayoutParams(lp); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java index b528b692e..1716fa049 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java @@ -16,7 +16,6 @@ package com.android.inputmethod.keyboard.internal; -import android.content.res.ColorStateList; import android.graphics.Typeface; import com.android.inputmethod.latin.utils.ResourceUtils; @@ -33,7 +32,7 @@ public final class KeyDrawParams { public int mHintLabelSize; public int mPreviewTextSize; - public ColorStateList mTextColorStateList; + public int mTextColor; public int mTextInactivatedColor; public int mTextShadowColor; public int mHintLetterColor; @@ -58,7 +57,7 @@ public final class KeyDrawParams { mHintLabelSize = copyFrom.mHintLabelSize; mPreviewTextSize = copyFrom.mPreviewTextSize; - mTextColorStateList = copyFrom.mTextColorStateList; + mTextColor = copyFrom.mTextColor; mTextInactivatedColor = copyFrom.mTextInactivatedColor; mTextShadowColor = copyFrom.mTextShadowColor; mHintLetterColor = copyFrom.mHintLetterColor; @@ -90,8 +89,8 @@ public final class KeyDrawParams { attr.mShiftedLetterHintRatio, mShiftedLetterHintSize); mHintLabelSize = selectTextSize(keyHeight, attr.mHintLabelRatio, mHintLabelSize); mPreviewTextSize = selectTextSize(keyHeight, attr.mPreviewTextRatio, mPreviewTextSize); - mTextColorStateList = - attr.mTextColorStateList != null ? attr.mTextColorStateList : mTextColorStateList; + + mTextColor = selectColor(attr.mTextColor, mTextColor); mTextInactivatedColor = selectColor(attr.mTextInactivatedColor, mTextInactivatedColor); mTextShadowColor = selectColor(attr.mTextShadowColor, mTextShadowColor); mHintLetterColor = selectColor(attr.mHintLetterColor, mHintLetterColor); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java index c3e0aa685..df386fce4 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java @@ -16,7 +16,6 @@ package com.android.inputmethod.keyboard.internal; -import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Typeface; import android.util.SparseIntArray; @@ -38,7 +37,7 @@ public final class KeyVisualAttributes { public final float mHintLabelRatio; public final float mPreviewTextRatio; - public final ColorStateList mTextColorStateList; + public final int mTextColor; public final int mTextInactivatedColor; public final int mTextShadowColor; public final int mHintLetterColor; @@ -119,7 +118,7 @@ public final class KeyVisualAttributes { mPreviewTextRatio = ResourceUtils.getFraction(keyAttr, R.styleable.Keyboard_Key_keyPreviewTextRatio); - mTextColorStateList = keyAttr.getColorStateList(R.styleable.Keyboard_Key_keyTextColor); + mTextColor = keyAttr.getColor(R.styleable.Keyboard_Key_keyTextColor, 0); mTextInactivatedColor = keyAttr.getColor( R.styleable.Keyboard_Key_keyTextInactivatedColor, 0); mTextShadowColor = keyAttr.getColor(R.styleable.Keyboard_Key_keyTextShadowColor, 0); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index da8bf7d69..79d088f2e 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -102,7 +102,7 @@ public final class KeyboardIconsSet { return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">"; } - static int getIconId(final String name) { + public static int getIconId(final String name) { Integer iconId = sNameToIdsMap.get(name); if (iconId != null) { return iconId; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java index 89221ba24..976038c10 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java @@ -29,6 +29,8 @@ import java.util.Locale; public final class KeyboardTextsSet { public static final String PREFIX_TEXT = "!text/"; + public static final String SWITCH_TO_ALPHA_KEY_LABEL = "label_to_alpha_key"; + private static final char BACKSLASH = Constants.CODE_BACKSLASH; private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java index 96acb1551..ed2db07a8 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java @@ -90,7 +90,7 @@ public final class KeyboardTextsTable { /* 8:20 */ "more_keys_for_s", /* 9:20 */ "more_keys_for_n", /* 10:20 */ "label_to_alpha_key", - /* 11:15 */ "more_keys_for_y", + /* 11:14 */ "more_keys_for_y", /* 12:13 */ "more_keys_for_d", /* 13:12 */ "more_keys_for_z", /* 14:10 */ "more_keys_for_t", @@ -3585,7 +3585,7 @@ public final class KeyboardTextsTable { private static final Object[] LANGUAGES_AND_TEXTS = { // "locale", TEXT_ARRAY, /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */ "DEFAULT", LANGUAGE_DEFAULT, /* 171/171 default */ - "af", LANGUAGE_af, /* 8/ 12 Afrikaans */ + "af", LANGUAGE_af, /* 7/ 12 Afrikaans */ "ar", LANGUAGE_ar, /* 58/110 Arabic */ "az", LANGUAGE_az_AZ, /* 8/ 17 Azerbaijani (Azerbaijan) */ "be", LANGUAGE_be_BY, /* 10/ 33 Belarusian (Belarus) */ diff --git a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java b/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java deleted file mode 100644 index 1c6a14efe..000000000 --- a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin; - -import android.util.Log; - -import com.android.inputmethod.latin.makedict.DictEncoder; -import com.android.inputmethod.latin.makedict.UnsupportedFormatException; -import com.android.inputmethod.latin.makedict.Ver4DictEncoder; -import com.android.inputmethod.latin.utils.FileUtils; - -import java.io.File; -import java.io.IOException; -import java.util.Map; - -abstract public class AbstractDictionaryWriter { - /** Used for Log actions from this class */ - private static final String TAG = AbstractDictionaryWriter.class.getSimpleName(); - - public AbstractDictionaryWriter() { - } - - abstract public void clear(); - - /** - * Add a unigram with an optional shortcut to the dictionary. - * @param word The word to add. - * @param shortcutTarget A shortcut target for this word, or null if none. - * @param frequency The frequency for this unigram. - * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored - * if shortcutTarget is null. - * @param isNotAWord true if this is not a word, i.e. shortcut only. - */ - abstract public void addUnigramWord(final String word, final String shortcutTarget, - final int frequency, final int shortcutFreq, final boolean isNotAWord); - - // TODO: Remove lastModifiedTime after making binary dictionary support forgetting curve. - abstract public void addBigramWords(final String word0, final String word1, - final int frequency, final boolean isValid, final long lastModifiedTime); - - abstract public void removeBigramWords(final String word0, final String word1); - - abstract protected void writeDictionary(final DictEncoder dictEncoder, - final Map<String, String> attributeMap) throws IOException, UnsupportedFormatException; - - public void write(final File file, final Map<String, String> attributeMap) { - try { - FileUtils.deleteRecursively(file); - file.mkdir(); - final DictEncoder dictEncoder = new Ver4DictEncoder(file); - writeDictionary(dictEncoder, attributeMap); - } catch (IOException e) { - Log.e(TAG, "IO exception while writing file", e); - } catch (UnsupportedFormatException e) { - Log.e(TAG, "Unsupported format", e); - } - } -} diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index c450a1d4f..851ecc042 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -28,9 +28,9 @@ import com.android.inputmethod.latin.makedict.FormatSpec; import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; import com.android.inputmethod.latin.makedict.WordProperty; +import com.android.inputmethod.latin.personalization.PersonalizationHelper; import com.android.inputmethod.latin.settings.NativeSuggestOptions; import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.JniUtils; import com.android.inputmethod.latin.utils.LanguageModelParam; import com.android.inputmethod.latin.utils.StringUtils; @@ -508,7 +508,9 @@ public final class BinaryDictionary extends Dictionary { */ @UsedForTesting public static int setCurrentTimeForTest(final int currentTime) { - return setCurrentTimeForTestNative(currentTime); + final int currentNativeTimestamp = setCurrentTimeForTestNative(currentTime); + PersonalizationHelper.currentTimeChangedForTesting(currentNativeTimestamp); + return currentNativeTimestamp; } @UsedForTesting diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index a7008379f..acbd919cd 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -229,7 +229,7 @@ final public class BinaryDictionaryGetter { private static boolean hackCanUseDictionaryFile(final Locale locale, final File f) { try { // Read the version of the file - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(f); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(f, 0, f.length()); final DictionaryHeader header = dictDecoder.readHeader(); final String version = header.mDictionaryOptions.mAttributes.get(VERSION_KEY); diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index ae9bdf3fc..c2941e424 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -78,7 +78,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { public ContactsBinaryDictionary(final Context context, final Locale locale, final File dictFile) { super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_CONTACTS, - false /* isUpdatable */, dictFile); + dictFile); mLocale = locale; mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale); registerObserver(context); @@ -114,14 +114,14 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { } @Override - public void loadDictionaryAsync() { - loadDeviceAccountsEmailAddresses(); - loadDictionaryAsyncForUri(ContactsContract.Profile.CONTENT_URI); + public void loadInitialContentsLocked() { + loadDeviceAccountsEmailAddressesLocked(); + loadDictionaryForUriLocked(ContactsContract.Profile.CONTENT_URI); // TODO: Switch this URL to the newer ContactsContract too - loadDictionaryAsyncForUri(Contacts.CONTENT_URI); + loadDictionaryForUriLocked(Contacts.CONTENT_URI); } - private void loadDeviceAccountsEmailAddresses() { + private void loadDeviceAccountsEmailAddressesLocked() { final List<String> accountVocabulary = AccountUtils.getDeviceAccountsEmailAddresses(mContext); if (accountVocabulary == null || accountVocabulary.isEmpty()) { @@ -131,12 +131,14 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { if (DEBUG) { Log.d(TAG, "loadAccountVocabulary: " + word); } - super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS, 0 /* shortcutFreq */, - false /* isNotAWord */); + runGCIfRequiredLocked(true /* mindsBlockByGC */); + addWordDynamicallyLocked(word, FREQUENCY_FOR_CONTACTS, null /* shortcut */, + 0 /* shortcutFreq */, false /* isNotAWord */, false /* isBlacklisted */, + BinaryDictionary.NOT_A_VALID_TIMESTAMP); } } - private void loadDictionaryAsyncForUri(final Uri uri) { + private void loadDictionaryForUriLocked(final Uri uri) { Cursor cursor = null; try { cursor = mContext.getContentResolver().query(uri, PROJECTION, null, null, null); @@ -145,7 +147,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { } if (cursor.moveToFirst()) { sContactCountAtLastRebuild = getContactCount(); - addWords(cursor); + addWordsLocked(cursor); } } catch (final SQLiteException e) { Log.e(TAG, "SQLiteException in the remote Contacts process.", e); @@ -166,12 +168,12 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { return false; } - private void addWords(final Cursor cursor) { + private void addWordsLocked(final Cursor cursor) { int count = 0; while (!cursor.isAfterLast() && count < MAX_CONTACT_COUNT) { String name = cursor.getString(INDEX_NAME); if (isValidName(name)) { - addName(name); + addNameLocked(name); ++count; } else { if (DEBUG_DUMP) { @@ -207,7 +209,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { * Adds the words in a name (e.g., firstname/lastname) to the binary dictionary along with their * bigrams depending on locale. */ - private void addName(final String name) { + private void addNameLocked(final String name) { int len = StringUtils.codePointCount(name); String prevWord = null; // TODO: Better tokenization for non-Latin writing systems @@ -226,13 +228,15 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { if (DEBUG) { Log.d(TAG, "addName " + name + ", " + word + ", " + prevWord); } - super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS, - 0 /* shortcutFreq */, false /* isNotAWord */); - if (!TextUtils.isEmpty(prevWord)) { - if (mUseFirstLastBigrams) { - super.addBigram(prevWord, word, FREQUENCY_FOR_CONTACTS_BIGRAM, - 0 /* lastModifiedTime */); - } + runGCIfRequiredLocked(true /* mindsBlockByGC */); + addWordDynamicallyLocked(word, FREQUENCY_FOR_CONTACTS, + null /* shortcut */, 0 /* shortcutFreq */, false /* isNotAWord */, + false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP); + if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) { + runGCIfRequiredLocked(true /* mindsBlockByGC */); + addBigramDynamicallyLocked(prevWord, word, + FREQUENCY_FOR_CONTACTS_BIGRAM, + BinaryDictionary.NOT_A_VALID_TIMESTAMP); } prevWord = word; } @@ -258,12 +262,12 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { } @Override - protected boolean needsToReloadBeforeWriting() { + protected boolean needsToReloadAfterCreation() { return true; } @Override - protected boolean hasContentChanged() { + protected boolean haveContentsChanged() { final long startTime = SystemClock.uptimeMillis(); final int contactCount = getContactCount(); if (contactCount > MAX_CONTACT_COUNT) { @@ -291,7 +295,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { if (cursor.moveToFirst()) { while (!cursor.isAfterLast()) { String name = cursor.getString(INDEX_NAME); - if (isValidName(name) && !isNameInDictionary(name)) { + if (isValidName(name) && !isNameInDictionaryLocked(name)) { if (DEBUG) { Log.d(TAG, "Contact name missing: " + name + " (runtime = " + (SystemClock.uptimeMillis() - startTime) + " ms)"); @@ -321,7 +325,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { /** * Checks if the words in a name are in the current binary dictionary. */ - private boolean isNameInDictionary(final String name) { + private boolean isNameInDictionaryLocked(final String name) { int len = StringUtils.codePointCount(name); String prevWord = null; for (int i = 0; i < len; i++) { @@ -332,11 +336,11 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { final int wordLen = StringUtils.codePointCount(word); if (wordLen < MAX_WORD_LENGTH && wordLen > 1) { if (!TextUtils.isEmpty(prevWord) && mUseFirstLastBigrams) { - if (!super.isValidBigramLocked(prevWord, word)) { + if (!isValidBigramLocked(prevWord, word)) { return false; } } else { - if (!super.isValidWordLocked(word)) { + if (!isValidWordLocked(word)) { return false; } } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java index 14e1baf41..d6178fcee 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java @@ -28,6 +28,7 @@ import com.android.inputmethod.latin.personalization.PersonalizationHelper; import com.android.inputmethod.latin.personalization.UserHistoryDictionary; import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.ExecutorUtils; import com.android.inputmethod.latin.utils.LanguageModelParam; import java.io.File; @@ -35,6 +36,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; @@ -137,7 +139,8 @@ public class DictionaryFacilitatorForSuggest { @UsedForTesting public DictionaryFacilitatorForSuggest(final Context context, final Locale locale, - final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles) { + final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles, + final Map<String, Map<String, String>> additionalDictAttributes) { mContext = context; mLocale = locale; mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0); @@ -154,6 +157,10 @@ public class DictionaryFacilitatorForSuggest { userHistoryDictionary.reloadDictionaryIfRequired(); userHistoryDictionary.waitAllTasksForTests(); setUserHistoryDictionary(userHistoryDictionary); + if (additionalDictAttributes.containsKey(dictType)) { + userHistoryDictionary.clearAndFlushDictionaryWithAdditionalAttributes( + additionalDictAttributes.get(dictType)); + } } else if (dictType.equals(Dictionary.TYPE_PERSONALIZATION)) { final PersonalizationDictionary personalizationDictionary = PersonalizationHelper.getPersonalizationDictionary(context, locale); @@ -162,6 +169,10 @@ public class DictionaryFacilitatorForSuggest { personalizationDictionary.reloadDictionaryIfRequired(); personalizationDictionary.waitAllTasksForTests(); setPersonalizationDictionary(personalizationDictionary); + if (additionalDictAttributes.containsKey(dictType)) { + personalizationDictionary.clearAndFlushDictionaryWithAdditionalAttributes( + additionalDictAttributes.get(dictType)); + } } else if (dictType.equals(Dictionary.TYPE_USER)) { final File file = dictionaryFiles.get(dictType); final UserBinaryDictionary userDictionary = new UserBinaryDictionary( @@ -204,8 +215,7 @@ public class DictionaryFacilitatorForSuggest { if (listener != null) { listener.onUpdateMainDictionaryAvailability(hasMainDictionary()); } - new Thread("InitializeBinaryDictionary") { - @Override + ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() { public void run() { final DictionaryCollection newMainDict = DictionaryFactory.createMainDictionaryFromManager(context, locale); @@ -215,7 +225,7 @@ public class DictionaryFacilitatorForSuggest { } mLatchForWaitingLoadingMainDictionary.countDown(); } - }.start(); + }); } // The main dictionary could have been loaded asynchronously. Don't cache the return value diff --git a/java/src/com/android/inputmethod/latin/DictionaryWriter.java b/java/src/com/android/inputmethod/latin/DictionaryWriter.java deleted file mode 100644 index b931c66d1..000000000 --- a/java/src/com/android/inputmethod/latin/DictionaryWriter.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin; - -import com.android.inputmethod.latin.makedict.DictEncoder; -import com.android.inputmethod.latin.makedict.FormatSpec; -import com.android.inputmethod.latin.makedict.FusionDictionary; -import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray; -import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; -import com.android.inputmethod.latin.makedict.ProbabilityInfo; -import com.android.inputmethod.latin.makedict.UnsupportedFormatException; -import com.android.inputmethod.latin.utils.CollectionUtils; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** - * An in memory dictionary for memorizing entries and writing a binary dictionary. - */ -public class DictionaryWriter extends AbstractDictionaryWriter { - private static final int BINARY_DICT_VERSION = FormatSpec.VERSION4; - private static final FormatSpec.FormatOptions FORMAT_OPTIONS = - new FormatSpec.FormatOptions(BINARY_DICT_VERSION, false /* hasTimestamp */); - - private FusionDictionary mFusionDictionary; - - public DictionaryWriter() { - clear(); - } - - @Override - public void clear() { - final HashMap<String, String> attributes = CollectionUtils.newHashMap(); - mFusionDictionary = new FusionDictionary(new PtNodeArray(), - new FusionDictionary.DictionaryOptions(attributes)); - } - - /** - * Adds a word unigram to the fusion dictionary. - */ - // TODO: Create "cache dictionary" to cache fresh words for frequently updated dictionaries, - // considering performance regression. - @Override - public void addUnigramWord(final String word, final String shortcutTarget, - final int probability, final int shortcutProbability, final boolean isNotAWord) { - if (shortcutTarget == null) { - mFusionDictionary.add(word, new ProbabilityInfo(probability), null, isNotAWord); - } else { - // TODO: Do this in the subclass, with this class taking an arraylist. - final ArrayList<WeightedString> shortcutTargets = CollectionUtils.newArrayList(); - shortcutTargets.add(new WeightedString(shortcutTarget, shortcutProbability)); - mFusionDictionary.add(word, new ProbabilityInfo(probability), shortcutTargets, - isNotAWord); - } - } - - @Override - public void addBigramWords(final String word0, final String word1, final int probability, - final boolean isValid, final long lastModifiedTime) { - mFusionDictionary.setBigram(word0, word1, new ProbabilityInfo(probability)); - } - - @Override - public void removeBigramWords(final String word0, final String word1) { - // This class don't support removing bigram words. - } - - @Override - protected void writeDictionary(final DictEncoder dictEncoder, - final Map<String, String> attributeMap) throws IOException, UnsupportedFormatException { - for (final Map.Entry<String, String> entry : attributeMap.entrySet()) { - mFusionDictionary.addOptionAttribute(entry.getKey(), entry.getValue()); - } - dictEncoder.writeDictionary(mFusionDictionary, FORMAT_OPTIONS); - } -} diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index f9ab9419b..26545acbd 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -29,9 +29,9 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CombinedFormatUtils; +import com.android.inputmethod.latin.utils.ExecutorUtils; import com.android.inputmethod.latin.utils.FileUtils; import com.android.inputmethod.latin.utils.LanguageModelParam; -import com.android.inputmethod.latin.utils.PrioritizedSerialExecutor; import java.io.File; import java.util.ArrayList; @@ -64,6 +64,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private static final int TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS = 100; private static final int TIMEOUT_FOR_READ_OPS_FOR_TESTS_IN_MILLISECONDS = 10000; + private static final int DEFAULT_MAX_UNIGRAM_COUNT = 10000; + private static final int DEFAULT_MAX_BIGRAM_COUNT = 10000; + /** * The maximum length of a word in this dictionary. */ @@ -80,9 +83,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private static final ConcurrentHashMap<String, DictionaryUpdateController> sDictNameDictionaryUpdateControllerMap = CollectionUtils.newConcurrentHashMap(); - private static final ConcurrentHashMap<String, PrioritizedSerialExecutor> - sDictNameExecutorMap = CollectionUtils.newConcurrentHashMap(); - /** The application context. */ protected final Context mContext; @@ -92,10 +92,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ private BinaryDictionary mBinaryDictionary; - // TODO: Remove and handle dictionaries in native code. - /** The in-memory dictionary used to generate the binary dictionary. */ - protected AbstractDictionaryWriter mDictionaryWriter; - /** * The name of this dictionary, used as a part of the filename for storing the binary * dictionary. Multiple dictionary instances with the same name is supported, with access @@ -106,9 +102,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** Dictionary locale */ private final Locale mLocale; - /** Whether to support dynamically updating the dictionary */ - private final boolean mIsUpdatable; - /** Dictionary file */ private final File mDictFile; @@ -128,23 +121,22 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { new AtomicReference<Runnable>(); /** - * Abstract method for loading the unigrams and bigrams of a given dictionary in a background - * thread. + * Abstract method for loading initial contents of a given dictionary. */ - protected abstract void loadDictionaryAsync(); + protected abstract void loadInitialContentsLocked(); /** - * Indicates that the source dictionary content has changed and a rebuild of the binary file is - * required. If it returns false, the next reload will only read the current binary dictionary - * from file. Note that the shared binary dictionary is locked when this is called. + * Indicates that the source dictionary contents have changed and a rebuild of the binary file + * is required. If it returns false, the next reload will only read the current binary + * dictionary from file. Note that the shared binary dictionary is locked when this is called. */ - protected abstract boolean hasContentChanged(); + protected abstract boolean haveContentsChanged(); private boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) { return formatVersion == FormatSpec.VERSION4; } - public boolean isValidDictionary() { + public boolean isValidDictionaryLocked() { return mBinaryDictionary.isValidDictionary(); } @@ -164,42 +156,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } /** - * Gets the executor for the given dictionary name. - */ - private static PrioritizedSerialExecutor getExecutor(final String dictName) { - PrioritizedSerialExecutor executor = sDictNameExecutorMap.get(dictName); - if (executor == null) { - synchronized(sDictNameExecutorMap) { - executor = new PrioritizedSerialExecutor(); - sDictNameExecutorMap.put(dictName, executor); - } - } - return executor; - } - - /** - * Shutdowns all executors and removes all executors from the executor map for testing. - */ - @UsedForTesting - public static void shutdownAllExecutors() { - synchronized(sDictNameExecutorMap) { - for (final PrioritizedSerialExecutor executor : sDictNameExecutorMap.values()) { - executor.shutdown(); - sDictNameExecutorMap.remove(executor); - } - } - } - - private static AbstractDictionaryWriter getDictionaryWriter( - final boolean isDynamicPersonalizationDictionary) { - if (isDynamicPersonalizationDictionary) { - return null; - } else { - return new DictionaryWriter(); - } - } - - /** * Creates a new expandable binary dictionary. * * @param context The application context of the parent. @@ -207,24 +163,18 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * name is supported. * @param locale the dictionary locale. * @param dictType the dictionary type, as a human-readable string - * @param isUpdatable whether to support dynamically updating the dictionary. Please note that - * dynamic dictionary has negative effects on memory space and computation time. * @param dictFile dictionary file path. if null, use default dictionary path based on * dictionary type. */ public ExpandableBinaryDictionary(final Context context, final String dictName, - final Locale locale, final String dictType, final boolean isUpdatable, - final File dictFile) { + final Locale locale, final String dictType, final File dictFile) { super(dictType); mDictName = dictName; mContext = context; mLocale = locale; - mIsUpdatable = isUpdatable; mDictFile = getDictFile(context, dictName, dictFile); mBinaryDictionary = null; mDictNameDictionaryUpdateController = getDictionaryUpdateController(dictName); - // Currently, only dynamic personalization dictionary is updatable. - mDictionaryWriter = getDictionaryWriter(isUpdatable); } public static File getDictFile(final Context context, final String dictName, @@ -243,20 +193,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ @Override public void close() { - getExecutor(mDictName).execute(new Runnable() { - @Override - public void run() { - if (mBinaryDictionary!= null) { - mBinaryDictionary.close(); - mBinaryDictionary = null; - } - } - }); - } - - protected void closeBinaryDictionary() { - // Ensure that no other threads are accessing the local binary dictionary. - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { if (mBinaryDictionary != null) { @@ -273,6 +210,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { attributeMap.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, mLocale.toString()); attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY, String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))); + attributeMap.put(DictionaryHeader.MAX_UNIGRAM_COUNT_KEY, + String.valueOf(DEFAULT_MAX_UNIGRAM_COUNT)); + attributeMap.put(DictionaryHeader.MAX_BIGRAM_COUNT_KEY, + String.valueOf(DEFAULT_MAX_BIGRAM_COUNT)); return attributeMap; } @@ -286,65 +227,52 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { mBinaryDictionary = null; } + private void createBinaryDictionaryLocked() { + BinaryDictionary.createEmptyDictFile(mDictFile.getAbsolutePath(), + DICTIONARY_FORMAT_VERSION, mLocale, getHeaderAttributeMap()); + } + + private void openBinaryDictionaryLocked() { + mBinaryDictionary = new BinaryDictionary( + mDictFile.getAbsolutePath(), 0 /* offset */, mDictFile.length(), + true /* useFullEditDistance */, mLocale, mDictType, true /* isUpdatable */); + } + protected void clear() { - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { - if (mDictionaryWriter == null) { - removeBinaryDictionaryLocked(); - BinaryDictionary.createEmptyDictFile(mDictFile.getAbsolutePath(), - DICTIONARY_FORMAT_VERSION, mLocale, getHeaderAttributeMap()); - mBinaryDictionary = new BinaryDictionary( - mDictFile.getAbsolutePath(), 0 /* offset */, mDictFile.length(), - true /* useFullEditDistance */, mLocale, mDictType, mIsUpdatable); - } else { - mDictionaryWriter.clear(); - } + removeBinaryDictionaryLocked(); + createBinaryDictionaryLocked(); + openBinaryDictionaryLocked(); } }); } /** - * Adds a word unigram to the dictionary. Used for loading a dictionary. - * @param word The word to add. - * @param shortcutTarget A shortcut target for this word, or null if none. - * @param frequency The frequency for this unigram. - * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored - * if shortcutTarget is null. - * @param isNotAWord true if this is not a word, i.e. shortcut only. - */ - protected void addWord(final String word, final String shortcutTarget, - final int frequency, final int shortcutFreq, final boolean isNotAWord) { - mDictionaryWriter.addUnigramWord(word, shortcutTarget, frequency, shortcutFreq, isNotAWord); - } - - /** - * Adds a word bigram in the dictionary. Used for loading a dictionary. - */ - protected void addBigram(final String prevWord, final String word, final int frequency, - final long lastModifiedTime) { - mDictionaryWriter.addBigramWords(prevWord, word, frequency, true /* isValid */, - lastModifiedTime); - } - - /** * Check whether GC is needed and run GC if required. */ protected void runGCIfRequired(final boolean mindsBlockByGC) { - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { - runGCIfRequiredInternalLocked(mindsBlockByGC); + runGCAfterAllPrioritizedTasksIfRequiredLocked(mindsBlockByGC); } }); } - private void runGCIfRequiredInternalLocked(final boolean mindsBlockByGC) { - // Calls to needsToRunGC() need to be serialized. + protected void runGCIfRequiredLocked(final boolean mindsBlockByGC) { + if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { + mBinaryDictionary.flushWithGC(); + } + } + + private void runGCAfterAllPrioritizedTasksIfRequiredLocked(final boolean mindsBlockByGC) { + // needsToRunGC() have to be called with lock. if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { if (setProcessingLargeTaskIfNot()) { // Run GC after currently existing time sensitive operations. - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { try { @@ -364,52 +292,50 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected void addWordDynamically(final String word, final int frequency, final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord, final boolean isBlacklisted, final int timestamp) { - if (!mIsUpdatable) { - Log.w(TAG, "addWordDynamically is called for non-updatable dictionary: " + mDictName); - return; - } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.addUnigramWord(word, frequency, shortcutTarget, shortcutFreq, + runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */); + addWordDynamicallyLocked(word, frequency, shortcutTarget, shortcutFreq, isNotAWord, isBlacklisted, timestamp); } }); } + protected void addWordDynamicallyLocked(final String word, final int frequency, + final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord, + final boolean isBlacklisted, final int timestamp) { + mBinaryDictionary.addUnigramWord(word, frequency, shortcutTarget, shortcutFreq, + isNotAWord, isBlacklisted, timestamp); + } + /** * Dynamically adds a word bigram in the dictionary. May overwrite an existing entry. */ protected void addBigramDynamically(final String word0, final String word1, final int frequency, final int timestamp) { - if (!mIsUpdatable) { - Log.w(TAG, "addBigramDynamically is called for non-updatable dictionary: " - + mDictName); - return; - } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.addBigramWords(word0, word1, frequency, timestamp); + runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */); + addBigramDynamicallyLocked(word0, word1, frequency, timestamp); } }); } + protected void addBigramDynamicallyLocked(final String word0, final String word1, + final int frequency, final int timestamp) { + mBinaryDictionary.addBigramWords(word0, word1, frequency, timestamp); + } + /** * Dynamically remove a word bigram in the dictionary. */ protected void removeBigramDynamically(final String word0, final String word1) { - if (!mIsUpdatable) { - Log.w(TAG, "removeBigramDynamically is called for non-updatable dictionary: " - + mDictName); - return; - } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); + runGCAfterAllPrioritizedTasksIfRequiredLocked(true /* mindsBlockByGC */); mBinaryDictionary.removeBigramWords(word0, word1); } }); @@ -425,12 +351,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected void addMultipleDictionaryEntriesDynamically( final ArrayList<LanguageModelParam> languageModelParams, final AddMultipleDictionaryEntriesCallback callback) { - if (!mIsUpdatable) { - Log.w(TAG, "addMultipleDictionaryEntriesDynamically is called for non-updatable " + - "dictionary: " + mDictName); - return; - } - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { final boolean locked = setProcessingLargeTaskIfNot(); @@ -461,7 +382,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } final AsyncResultHolder<ArrayList<SuggestedWordInfo>> holder = new AsyncResultHolder<ArrayList<SuggestedWordInfo>>(); - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { if (mBinaryDictionary == null) { @@ -492,15 +413,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @Override public boolean isValidWord(final String word) { reloadDictionaryIfRequired(); - return isValidWordInner(word); - } - - protected boolean isValidWordInner(final String word) { if (processingLargeTask()) { return false; } final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); - getExecutor(mDictName).executePrioritized(new Runnable() { + ExecutorUtils.getExecutor(mDictName).executePrioritized(new Runnable() { @Override public void run() { holder.set(isValidWordLocked(word)); @@ -532,7 +449,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Loads the current binary dictionary from internal storage. Assumes the dictionary file * exists. */ - private void loadBinaryDictionary() { + private void loadBinaryDictionaryLocked() { if (DEBUG) { Log.d(TAG, "Loading binary dictionary: " + mDictName + " request=" + mDictNameDictionaryUpdateController.mLastUpdateRequestTime + " update=" @@ -548,65 +465,40 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } catch (InterruptedException e) { } } - - final String filename = mDictFile.getAbsolutePath(); - final long length = mDictFile.length(); - - // Build the new binary dictionary - final BinaryDictionary newBinaryDictionary = new BinaryDictionary(filename, 0 /* offset */, - length, true /* useFullEditDistance */, null, mDictType, mIsUpdatable); - - // Ensure all threads accessing the current dictionary have finished before - // swapping in the new one. - // TODO: Ensure multi-thread assignment of mBinaryDictionary. final BinaryDictionary oldBinaryDictionary = mBinaryDictionary; - getExecutor(mDictName).executePrioritized(new Runnable() { - @Override - public void run() { - mBinaryDictionary = newBinaryDictionary; - if (oldBinaryDictionary != null) { - oldBinaryDictionary.close(); - } - } - }); + openBinaryDictionaryLocked(); + if (oldBinaryDictionary != null) { + oldBinaryDictionary.close(); + } } /** * Abstract method for checking if it is required to reload the dictionary before writing * a binary dictionary. */ - abstract protected boolean needsToReloadBeforeWriting(); + abstract protected boolean needsToReloadAfterCreation(); /** - * Writes a new binary dictionary based on the contents of the fusion dictionary. + * Create a new binary dictionary and load initial contents. */ - private void writeBinaryDictionary() { + private void createNewDictionaryLocked() { if (DEBUG) { Log.d(TAG, "Generating binary dictionary: " + mDictName + " request=" + mDictNameDictionaryUpdateController.mLastUpdateRequestTime + " update=" + mDictNameDictionaryUpdateController.mLastUpdateTime); } - if (needsToReloadBeforeWriting()) { - mDictionaryWriter.clear(); - loadDictionaryAsync(); - mDictionaryWriter.write(mDictFile, getHeaderAttributeMap()); + removeBinaryDictionaryLocked(); + createBinaryDictionaryLocked(); + openBinaryDictionaryLocked(); + loadInitialContentsLocked(); + mBinaryDictionary.flushWithGC(); + } + + private void flushDictionaryLocked() { + if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { + mBinaryDictionary.flushWithGC(); } else { - if (mBinaryDictionary == null || !isValidDictionary() - // TODO: remove the check below - || !matchesExpectedBinaryDictFormatVersionForThisType( - mBinaryDictionary.getFormatVersion())) { - if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) { - Log.e(TAG, "Can't remove a file: " + mDictFile.getName()); - } - BinaryDictionary.createEmptyDictFile(mDictFile.getAbsolutePath(), - DICTIONARY_FORMAT_VERSION, mLocale, getHeaderAttributeMap()); - } else { - if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { - mBinaryDictionary.flushWithGC(); - } else { - mBinaryDictionary.flush(); - } - } + mBinaryDictionary.flush(); } } @@ -662,57 +554,43 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private final void reloadDictionary() { // Ensure that only one thread attempts to read or write to the shared binary dictionary // file at the same time. - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { try { final long time = System.currentTimeMillis(); - final boolean dictionaryFileExists = dictionaryFileExists(); - if (mDictNameDictionaryUpdateController.isOutOfDate() - || !dictionaryFileExists) { - // If the shared dictionary file does not exist or is out of date, the - // first instance that acquires the lock will generate a new one. - if (hasContentChanged() || !dictionaryFileExists) { - // If the source content has changed or the dictionary does not exist, - // rebuild the binary dictionary. Empty dictionaries are supported (in - // the case where loadDictionaryAsync() adds nothing) in order to - // provide a uniform framework. - mDictNameDictionaryUpdateController.mLastUpdateTime = time; - writeBinaryDictionary(); - loadBinaryDictionary(); - } else { - // If not, the reload request was unnecessary so revert - // LastUpdateRequestTime to LastUpdateTime. - mDictNameDictionaryUpdateController.mLastUpdateRequestTime = - mDictNameDictionaryUpdateController.mLastUpdateTime; - } + final boolean openedDictIsOutOfDate = + mDictNameDictionaryUpdateController.isOutOfDate(); + if (!dictionaryFileExists() + || (openedDictIsOutOfDate && haveContentsChanged())) { + // If the shared dictionary file does not exist or is out of date and + // contents have been updated, the first instance that acquires the lock + // will generate a new one + mDictNameDictionaryUpdateController.mLastUpdateTime = time; + createNewDictionaryLocked(); + } else if (openedDictIsOutOfDate) { + // If not, the reload request was unnecessary so revert + // LastUpdateRequestTime to LastUpdateTime. + mDictNameDictionaryUpdateController.mLastUpdateRequestTime = + mDictNameDictionaryUpdateController.mLastUpdateTime; } else if (mBinaryDictionary == null || mPerInstanceDictionaryUpdateController.mLastUpdateTime < mDictNameDictionaryUpdateController.mLastUpdateTime) { // Otherwise, if the local dictionary is older than the shared dictionary, // load the shared dictionary. - loadBinaryDictionary(); + loadBinaryDictionaryLocked(); } - // If we just loaded the binary dictionary, then mBinaryDictionary is not - // up-to-date yet so it's useless to test it right away. Schedule the check - // for right after it's loaded instead. - getExecutor(mDictName).executePrioritized(new Runnable() { - @Override - public void run() { - if (mBinaryDictionary != null && !(isValidDictionary() - // TODO: remove the check below - && matchesExpectedBinaryDictFormatVersionForThisType( - mBinaryDictionary.getFormatVersion()))) { - // Binary dictionary or its format version is not valid. Regenerate - // the dictionary file. writeBinaryDictionary will remove the - // existing files if appropriate. - mDictNameDictionaryUpdateController.mLastUpdateTime = time; - writeBinaryDictionary(); - loadBinaryDictionary(); - } - mPerInstanceDictionaryUpdateController.mLastUpdateTime = time; - } - }); + if (mBinaryDictionary != null && !(isValidDictionaryLocked() + // TODO: remove the check below + && matchesExpectedBinaryDictFormatVersionForThisType( + mBinaryDictionary.getFormatVersion()))) { + // Binary dictionary or its format version is not valid. Regenerate + // the dictionary file. writeBinaryDictionary will remove the + // existing files if appropriate. + mDictNameDictionaryUpdateController.mLastUpdateTime = time; + createNewDictionaryLocked(); + } + mPerInstanceDictionaryUpdateController.mLastUpdateTime = time; } finally { mDictNameDictionaryUpdateController.mProcessingLargeTask.set(false); } @@ -726,17 +604,17 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } /** - * Generate binary dictionary using DictionaryWriter. + * Flush binary dictionary to dictionary file. */ protected void asyncFlushBinaryDictionary() { final Runnable newTask = new Runnable() { @Override public void run() { - writeBinaryDictionary(); + flushDictionaryLocked(); } }; final Runnable oldTask = mUnfinishedFlushingTask.getAndSet(newTask); - getExecutor(mDictName).replaceAndExecute(oldTask, newTask); + ExecutorUtils.getExecutor(mDictName).replaceAndExecute(oldTask, newTask); } /** @@ -757,7 +635,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @UsedForTesting public boolean isInUnderlyingBinaryDictionaryForTests(final String word) { final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { if (mDictType == Dictionary.TYPE_USER_HISTORY) { @@ -771,7 +649,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @UsedForTesting public void waitAllTasksForTests() { final CountDownLatch countDownLatch = new CountDownLatch(1); - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { countDownLatch.countDown(); @@ -787,7 +665,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @UsedForTesting public void dumpAllWordsForDebug() { reloadDictionaryIfRequired(); - getExecutor(mDictName).execute(new Runnable() { + ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { @Override public void run() { Log.d(TAG, "Dump dictionary: " + mDictName); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 793c1c4ac..4c2454c32 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -172,7 +172,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } public void onCreate() { - final Resources res = getOwnerInstance().getResources(); + final LatinIME latinIme = getOwnerInstance(); + if (latinIme == null) { + return; + } + final Resources res = latinIme.getResources(); mDelayUpdateSuggestions = res.getInteger(R.integer.config_delay_update_suggestions); mDelayUpdateShiftState = res.getInteger(R.integer.config_delay_update_shift_state); mDoubleSpacePeriodTimeout = @@ -182,6 +186,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void handleMessage(final Message msg) { final LatinIME latinIme = getOwnerInstance(); + if (latinIme == null) { + return; + } final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; switch (msg.what) { case MSG_UPDATE_SUGGESTION_STRIP: @@ -239,7 +246,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } public void postResumeSuggestions() { - if (!getOwnerInstance().mSettings.getCurrent().isSuggestionStripVisible()) { + final LatinIME latinIme = getOwnerInstance(); + if (latinIme == null) { + return; + } + if (!latinIme.mSettings.getCurrent().isSuggestionStripVisible()) { return; } removeMessages(MSG_RESUME_SUGGESTIONS); @@ -326,6 +337,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen resetPendingImsCallback(); mIsOrientationChanging = true; final LatinIME latinIme = getOwnerInstance(); + if (latinIme == null) { + return; + } if (latinIme.isInputViewShown()) { latinIme.mKeyboardSwitcher.saveKeyboardState(); } @@ -362,8 +376,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mPendingSuccessiveImsCallback = true; } final LatinIME latinIme = getOwnerInstance(); - executePendingImsCallback(latinIme, editorInfo, restarting); - latinIme.onStartInputInternal(editorInfo, restarting); + if (latinIme != null) { + executePendingImsCallback(latinIme, editorInfo, restarting); + latinIme.onStartInputInternal(editorInfo, restarting); + } } } @@ -381,9 +397,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen PENDING_IMS_CALLBACK_DURATION); } final LatinIME latinIme = getOwnerInstance(); - executePendingImsCallback(latinIme, editorInfo, restarting); - latinIme.onStartInputViewInternal(editorInfo, restarting); - mAppliedEditorInfo = editorInfo; + if (latinIme != null) { + executePendingImsCallback(latinIme, editorInfo, restarting); + latinIme.onStartInputViewInternal(editorInfo, restarting); + mAppliedEditorInfo = editorInfo; + } } } @@ -393,8 +411,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHasPendingFinishInputView = true; } else { final LatinIME latinIme = getOwnerInstance(); - latinIme.onFinishInputViewInternal(finishingInput); - mAppliedEditorInfo = null; + if (latinIme != null) { + latinIme.onFinishInputViewInternal(finishingInput); + mAppliedEditorInfo = null; + } } } @@ -404,8 +424,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHasPendingFinishInput = true; } else { final LatinIME latinIme = getOwnerInstance(); - executePendingImsCallback(latinIme, null, false); - latinIme.onFinishInputInternal(); + if (latinIme != null) { + executePendingImsCallback(latinIme, null, false); + latinIme.onFinishInputInternal(); + } } } } @@ -857,7 +879,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // This will set the punctuation suggestions if next word suggestion is off; // otherwise it will clear the suggestion strip. - setNeutralSuggestionStripInternal(false /* needsInputViewShown */); + setNeutralSuggestionStripInternal(); mHandler.cancelUpdateSuggestionStrip(); mHandler.cancelDoubleSpacePeriodTimer(); @@ -1022,23 +1044,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */, false /* isObsoleteSuggestions */, false /* isPrediction */); // When in fullscreen mode, show completions generated by the application forcibly - setSuggestedWords(suggestedWords, true /* isSuggestionStripVisible */, - true /* needsInputViewShown */); + setSuggestedWords(suggestedWords, true /* isSuggestionStripVisible */); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions); } } - private void setSuggestionStripShownInternal(final boolean isSuggestionStripVisible, - final boolean needsInputViewShown) { + private void setSuggestionStripShownInternal(final boolean isSuggestionStripVisible) { // TODO: Modify this if we support suggestions with hard keyboard if (!onEvaluateInputViewShown() || !hasSuggestionStripView()) { return; } - final boolean inputViewShown = mKeyboardSwitcher.isShowingMainKeyboardOrEmojiPalettes(); - final boolean shouldShowSuggestions = isSuggestionStripVisible - && (needsInputViewShown ? inputViewShown : true); - if (shouldShowSuggestions) { + if (isSuggestionStripVisible) { mSuggestionStripView.setVisibility(View.VISIBLE); } else { mSuggestionStripView.setVisibility(isFullscreenMode() ? View.GONE : View.INVISIBLE); @@ -1325,8 +1342,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Nothing to do so far. } - // TODO[IL]: Define a clear interface for this - public boolean isSuggestionStripVisible() { + private boolean isSuggestionStripVisible() { if (!hasSuggestionStripView()) { return false; } @@ -1350,7 +1366,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return currentSettings.isSuggestionsRequested(); } - @Override public boolean hasSuggestionStripView() { return null != mSuggestionStripView; } @@ -1370,7 +1385,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // TODO[IL]: Define a clear interface for this public void setSuggestedWords(final SuggestedWords suggestedWords, - final boolean isSuggestionStripVisible, final boolean needsInputViewShown) { + final boolean isSuggestionStripVisible) { mInputLogic.setSuggestedWords(suggestedWords); if (!hasSuggestionStripView()) { return; @@ -1390,7 +1405,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype())); } mKeyboardSwitcher.onAutoCorrectionStateChanged(suggestedWords.mWillAutoCorrect); - setSuggestionStripShownInternal(isSuggestionStripVisible, needsInputViewShown); + setSuggestionStripShownInternal(isSuggestionStripVisible); } // TODO[IL]: Move this out of LatinIME. @@ -1476,8 +1491,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen setNeutralSuggestionStrip(); } else { mInputLogic.mWordComposer.setAutoCorrection(autoCorrection); - setSuggestedWords( - suggestedWords, isSuggestionStripVisible(), true /* needsInputViewShown */); + setSuggestedWords(suggestedWords, isSuggestionStripVisible()); } // Cache the auto-correction in accessibility code so we can speak it if the user // touches a key that will insert it. @@ -1506,14 +1520,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // punctuation suggestions (if it's disabled). @Override public void setNeutralSuggestionStrip() { - setNeutralSuggestionStripInternal(true /* needsInputViewShown */); + setNeutralSuggestionStripInternal(); } - private void setNeutralSuggestionStripInternal(final boolean needsInputViewShown) { + private void setNeutralSuggestionStripInternal() { final SettingsValues currentSettings = mSettings.getCurrent(); final SuggestedWords neutralSuggestions = currentSettings.mBigramPredictionEnabled ? SuggestedWords.EMPTY : currentSettings.mSpacingAndPunctuations.mSuggestPuncList; - setSuggestedWords(neutralSuggestions, isSuggestionStripVisible(), needsInputViewShown); + setSuggestedWords(neutralSuggestions, isSuggestionStripVisible()); } // TODO: Make this private diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 30b20a335..323256d1c 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -483,12 +483,16 @@ public final class RichInputConnection { * * @param start the character index where the selection should start. * @param end the character index where the selection should end. - * @return Returns true on success, false if the input connection is no longer valid either when - * setting the selection or when retrieving the text cache at that point. + * @return Returns true on success, false on failure: either the input connection is no longer + * valid when setting the selection or when retrieving the text cache at that point, or + * invalid arguments were passed. */ public boolean setSelection(final int start, final int end) { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); + if (start < 0 || end < 0) { + return false; + } mExpectedSelStart = start; mExpectedSelEnd = end; if (null != mIC) { diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 499a98d65..1747eeeda 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -134,12 +134,17 @@ public final class Suggest { mDictionaryFacilitator.getSuggestions(wordComposerForLookup, prevWordForBigram, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, SESSION_TYPING, suggestionsSet, rawSuggestions); + + final boolean isFirstCharCapitalized = wordComposer.isFirstCharCapitalized(); + final boolean isAllUpperCase = wordComposer.isAllUpperCase(); final String firstSuggestion; final String whitelistedWord; if (suggestionsSet.isEmpty()) { whitelistedWord = firstSuggestion = null; } else { - final SuggestedWordInfo firstSuggestedWordInfo = suggestionsSet.first(); + final SuggestedWordInfo firstSuggestedWordInfo = getTransformedSuggestedWordInfo( + suggestionsSet.first(), mLocale, isAllUpperCase, isFirstCharCapitalized, + trailingSingleQuotesCount); firstSuggestion = firstSuggestedWordInfo.mWord; if (SuggestedWordInfo.KIND_WHITELIST != firstSuggestedWordInfo.mKind) { whitelistedWord = null; @@ -148,6 +153,8 @@ public final class Suggest { } } + final boolean isPrediction = !wordComposer.isComposingWord(); + // We allow auto-correction if we have a whitelisted word, or if the word is not a valid // word of more than 1 char, except if the first suggestion is the same as the typed string // because in this case if it's strong enough to auto-correct that will mistakenly designate @@ -155,10 +162,10 @@ public final class Suggest { // TODO: stop relying on indices to find where is the auto-correction in the suggested // words, and correct this test. final boolean allowsToBeAutoCorrected = (null != whitelistedWord - && !whitelistedWord.equals(consideredWord)) + && !whitelistedWord.equals(typedWord)) || (consideredWord.length() > 1 && !mDictionaryFacilitator.isValidWord( consideredWord, wordComposer.isFirstCharCapitalized()) - && !consideredWord.equals(firstSuggestion)); + && !typedWord.equals(firstSuggestion)); final boolean hasAutoCorrection; // TODO: using isCorrectionEnabled here is not very good. It's probably useless, because @@ -166,7 +173,7 @@ public final class Suggest { // same time, it feels wrong that the SuggestedWord object includes information about // the current settings. It may also be useful to know, when the setting is off, whether // the word *would* have been auto-corrected. - if (!isCorrectionEnabled || !allowsToBeAutoCorrected || !wordComposer.isComposingWord() + if (!isCorrectionEnabled || !allowsToBeAutoCorrected || isPrediction || suggestionsSet.isEmpty() || wordComposer.hasDigits() || wordComposer.isMostlyCaps() || wordComposer.isResumed() || !mDictionaryFacilitator.hasMainDictionary() @@ -188,8 +195,6 @@ public final class Suggest { final ArrayList<SuggestedWordInfo> suggestionsContainer = CollectionUtils.newArrayList(suggestionsSet); final int suggestionsCount = suggestionsContainer.size(); - final boolean isFirstCharCapitalized = wordComposer.isFirstCharCapitalized(); - final boolean isAllUpperCase = wordComposer.isAllUpperCase(); if (isFirstCharCapitalized || isAllUpperCase || 0 != trailingSingleQuotesCount) { for (int i = 0; i < suggestionsCount; ++i) { final SuggestedWordInfo wordInfo = suggestionsContainer.get(i); @@ -226,10 +231,9 @@ public final class Suggest { // 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. - !allowsToBeAutoCorrected /* typedWordValid */, + !isPrediction && !allowsToBeAutoCorrected /* typedWordValid */, hasAutoCorrection, /* willAutoCorrect */ - false /* isObsoleteSuggestions */, - !wordComposer.isComposingWord() /* isPrediction */, sequenceNumber)); + false /* isObsoleteSuggestions */, isPrediction, sequenceNumber)); } // Retrieves suggestions for the batch input diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 46df3e88c..06bc90c97 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -69,7 +69,7 @@ public class SuggestedWords { final boolean isPrediction, final int sequenceNumber) { this(suggestedWordInfoList, rawSuggestions, - suggestedWordInfoList.isEmpty() ? null + (suggestedWordInfoList.isEmpty() || isPrediction) ? null : suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord, typedWordValid, willAutoCorrect, isObsoleteSuggestions, isPrediction, sequenceNumber); diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 3e3cbf063..8078ab541 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -86,8 +86,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { public UserBinaryDictionary(final Context context, final Locale locale, final boolean alsoUseMoreRestrictiveLocales, final File dictFile) { - super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_USER, - false /* isUpdatable */, dictFile); + super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_USER, dictFile); if (null == locale) throw new NullPointerException(); // Catch the error earlier final String localeStr = locale.toString(); if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) { @@ -130,7 +129,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { } @Override - public void loadDictionaryAsync() { + public void loadInitialContentsLocked() { // 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. @@ -182,7 +181,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { try { cursor = mContext.getContentResolver().query( Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null); - addWords(cursor); + addWordsLocked(cursor); } catch (final SQLiteException e) { Log.e(TAG, "SQLiteException in the remote User dictionary process.", e); } finally { @@ -236,7 +235,7 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { } } - private void addWords(final Cursor cursor) { + private void addWordsLocked(final Cursor cursor) { final boolean hasShortcutColumn = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; if (cursor == null) return; if (cursor.moveToFirst()) { @@ -250,12 +249,16 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency); // Safeguard against adding really long words. if (word.length() < MAX_WORD_LENGTH) { - super.addWord(word, null, adjustedFrequency, 0 /* shortcutFreq */, - false /* isNotAWord */); - } - if (null != shortcut && shortcut.length() < MAX_WORD_LENGTH) { - super.addWord(shortcut, word, adjustedFrequency, USER_DICT_SHORTCUT_FREQUENCY, - true /* isNotAWord */); + runGCIfRequiredLocked(true /* mindsBlockByGC */); + addWordDynamicallyLocked(word, adjustedFrequency, null /* shortcutTarget */, + 0 /* shortcutFreq */, false /* isNotAWord */, + false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP); + if (null != shortcut && shortcut.length() < MAX_WORD_LENGTH) { + runGCIfRequiredLocked(true /* mindsBlockByGC */); + addWordDynamicallyLocked(shortcut, adjustedFrequency, word, + USER_DICT_SHORTCUT_FREQUENCY, true /* isNotAWord */, + false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP); + } } cursor.moveToNext(); } @@ -263,12 +266,12 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { } @Override - protected boolean hasContentChanged() { + protected boolean haveContentsChanged() { return true; } @Override - protected boolean needsToReloadBeforeWriting() { + protected boolean needsToReloadAfterCreation() { return true; } } diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 045d06f0e..f2f9f1e68 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -1360,10 +1360,12 @@ public final class InputLogic { }}); } else { // We found suggestion spans in the word. We'll create the SuggestedWords out of - // them, and make willAutoCorrect false. + // them, and make willAutoCorrect false. We make typedWordValid false, because the + // color of the word in the suggestion strip changes according to this parameter, + // and false gives the correct color. final SuggestedWords suggestedWords = new SuggestedWords(suggestions, null /* rawSuggestions */, typedWord, - true /* typedWordValid */, false /* willAutoCorrect */, + false /* typedWordValid */, false /* willAutoCorrect */, false /* isObsoleteSuggestions */, false /* isPrediction */, SuggestedWords.NOT_A_SEQUENCE_NUMBER); mIsAutoCorrectionIndicatorOn = false; diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java index b09e20591..db96de305 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java @@ -139,7 +139,7 @@ class InputLogicHandler implements Handler.Callback { forEnd /* dismissGestureFloatingPreviewText */); if (forEnd) { mInBatchInput = false; - // The following call schedules onEndBatchInputAsyncInternal + // The following call schedules onEndBatchInputInternal // to be called on the UI thread. mLatinIME.mHandler.onEndBatchInput(suggestedWords); } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java index b534ebeff..25e1bcd25 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java @@ -357,7 +357,7 @@ public final class BinaryDictDecoderUtils { * @return true if it's a binary dictionary, false otherwise */ public static boolean isBinaryDictionary(final File file) { - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, 0, file.length()); if (dictDecoder == null) { return false; } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 989ca4b2f..90e7400fb 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -237,7 +237,7 @@ public final class BinaryDictIOUtils { final File file, final long offset, final long length) throws FileNotFoundException, IOException, UnsupportedFormatException { final byte[] buffer = new byte[HEADER_READING_BUFFER_SIZE]; - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, offset, length, new DictDecoder.DictionaryBufferFactory() { @Override public DictBuffer getDictionaryBuffer(File file) @@ -251,8 +251,7 @@ public final class BinaryDictIOUtils { inStream.close(); } } - } - ); + }); if (dictDecoder == null) { return null; } diff --git a/java/src/com/android/inputmethod/latin/makedict/DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/DictEncoder.java index a5dc45691..678c5ca6b 100644 --- a/java/src/com/android/inputmethod/latin/makedict/DictEncoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/DictEncoder.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.makedict; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions; import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode; @@ -25,6 +26,7 @@ import java.io.IOException; * An interface of binary dictionary encoder. */ public interface DictEncoder { + @UsedForTesting public void writeDictionary(final FusionDictionary dict, final FormatOptions formatOptions) throws IOException, UnsupportedFormatException; diff --git a/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java b/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java index b99e281da..b32eb9195 100644 --- a/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java +++ b/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java @@ -38,6 +38,14 @@ public final class DictionaryHeader { public static final String DICTIONARY_DATE_KEY = "date"; public static final String HAS_HISTORICAL_INFO_KEY = "HAS_HISTORICAL_INFO"; public static final String USES_FORGETTING_CURVE_KEY = "USES_FORGETTING_CURVE"; + public static final String FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY = + "FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP"; + public static final String FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY = + "FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID"; + public static final String FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY = + "FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS"; + public static final String MAX_UNIGRAM_COUNT_KEY = "MAX_UNIGRAM_COUNT"; + public static final String MAX_BIGRAM_COUNT_KEY = "MAX_BIGRAM_COUNT"; public static final String ATTRIBUTE_VALUE_TRUE = "1"; public DictionaryHeader(final int headerSize, final DictionaryOptions dictionaryOptions, diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index c7635eff9..9abecbfec 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -326,30 +326,34 @@ public final class FormatSpec { * Returns new dictionary decoder. * * @param dictFile the dictionary file. + * @param offset the offset in the file. + * @param length the length of the file, in bytes. * @param bufferType The type of buffer, as one of USE_* in DictDecoder. * @return new dictionary decoder if the dictionary file exists, otherwise null. */ - public static DictDecoder getDictDecoder(final File dictFile, final int bufferType) { + public static DictDecoder getDictDecoder(final File dictFile, final long offset, + final long length, final int bufferType) { if (dictFile.isDirectory()) { return new Ver4DictDecoder(dictFile, bufferType); } else if (dictFile.isFile()) { - return new Ver2DictDecoder(dictFile, bufferType); + return new Ver2DictDecoder(dictFile, offset, length, bufferType); } return null; } - public static DictDecoder getDictDecoder(final File dictFile, - final DictionaryBufferFactory factory) { + public static DictDecoder getDictDecoder(final File dictFile, final long offset, + final long length, final DictionaryBufferFactory factory) { if (dictFile.isDirectory()) { return new Ver4DictDecoder(dictFile, factory); } else if (dictFile.isFile()) { - return new Ver2DictDecoder(dictFile, factory); + return new Ver2DictDecoder(dictFile, offset, length, factory); } return null; } - public static DictDecoder getDictDecoder(final File dictFile) { - return getDictDecoder(dictFile, DictDecoder.USE_READONLY_BYTEBUFFER); + public static DictDecoder getDictDecoder(final File dictFile, final long offset, + final long length) { + return getDictDecoder(dictFile, offset, length, DictDecoder.USE_READONLY_BYTEBUFFER); } private FormatSpec() { diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java index bf776cfc5..ae1e443c5 100644 --- a/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java +++ b/java/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java @@ -116,13 +116,18 @@ public class Ver2DictDecoder extends AbstractDictDecoder { } protected final File mDictionaryBinaryFile; + protected final long mOffset; + protected final long mLength; // TODO: Remove mBufferFactory and mDictBuffer from this class members because they are now // used only for testing. private final DictionaryBufferFactory mBufferFactory; protected DictBuffer mDictBuffer; - /* package */ Ver2DictDecoder(final File file, final int factoryFlag) { + /* package */ Ver2DictDecoder(final File file, final long offset, final long length, + final int factoryFlag) { mDictionaryBinaryFile = file; + mOffset = offset; + mLength = length; mDictBuffer = null; if ((factoryFlag & MASK_DICTBUFFER) == USE_READONLY_BYTEBUFFER) { mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory(); @@ -135,8 +140,11 @@ public class Ver2DictDecoder extends AbstractDictDecoder { } } - /* package */ Ver2DictDecoder(final File file, final DictionaryBufferFactory factory) { + /* package */ Ver2DictDecoder(final File file, final long offset, final long length, + final DictionaryBufferFactory factory) { mDictionaryBinaryFile = file; + mOffset = offset; + mLength = length; mBufferFactory = factory; } @@ -164,9 +172,9 @@ public class Ver2DictDecoder extends AbstractDictDecoder { public DictionaryHeader readHeader() throws IOException, UnsupportedFormatException { // dictType is not being used in dicttool. Passing an empty string. final BinaryDictionary binaryDictionary = new BinaryDictionary( - mDictionaryBinaryFile.getAbsolutePath(), 0 /* offset */, - mDictionaryBinaryFile.length() /* length */, true /* useFullEditDistance */, - null /* locale */, "" /* dictType */, false /* isUpdatable */); + mDictionaryBinaryFile.getAbsolutePath(), mOffset, mLength, + true /* useFullEditDistance */, null /* locale */, "" /* dictType */, + false /* isUpdatable */); final DictionaryHeader header = binaryDictionary.getHeader(); binaryDictionary.close(); if (header == null) { diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index d3734d693..074ec4074 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -27,10 +27,8 @@ import com.android.inputmethod.latin.utils.LanguageModelParam; import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.concurrent.TimeUnit; /** * This class is a base class of a dictionary that supports decaying for the personalized language @@ -49,14 +47,13 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB /** The locale for this dictionary. */ public final Locale mLocale; - private final String mDictName; + private Map<String, String> mAdditionalAttributeMap = null; protected DecayingExpandableBinaryDictionaryBase(final Context context, final String dictName, final Locale locale, final String dictionaryType, final File dictFile) { - super(context, dictName, locale, dictionaryType, true /* isUpdatable */, dictFile); + super(context, dictName, locale, dictionaryType, dictFile); mLocale = locale; - mDictName = dictName; if (mLocale != null && mLocale.toString().length() > 1) { reloadDictionaryIfRequired(); } @@ -78,25 +75,24 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB @Override protected Map<String, String> getHeaderAttributeMap() { - HashMap<String, String> attributeMap = new HashMap<String, String>(); + final Map<String, String> attributeMap = super.getHeaderAttributeMap(); + if (mAdditionalAttributeMap != null) { + attributeMap.putAll(mAdditionalAttributeMap); + } attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY, DictionaryHeader.ATTRIBUTE_VALUE_TRUE); attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY, DictionaryHeader.ATTRIBUTE_VALUE_TRUE); - attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, mDictName); - attributeMap.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, mLocale.toString()); - attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY, - String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()))); return attributeMap; } @Override - protected boolean hasContentChanged() { + protected boolean haveContentsChanged() { return false; } @Override - protected boolean needsToReloadBeforeWriting() { + protected boolean needsToReloadAfterCreation() { return false; } @@ -140,8 +136,8 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB } @Override - protected void loadDictionaryAsync() { - // Never loaded to memory in Java side. + protected void loadInitialContentsLocked() { + // No initial contents. } @UsedForTesting @@ -152,7 +148,14 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB asyncFlushBinaryDictionary(); } - /* package */ void decayIfNeeded() { + @UsedForTesting + public void clearAndFlushDictionaryWithAdditionalAttributes( + final Map<String, String> attributeMap) { + mAdditionalAttributeMap = attributeMap; + clearAndFlushDictionary(); + } + + /* package */ void runGCIfRequired() { runGCIfRequired(false /* mindsBlockByGC */); } } diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java index e9ca662e7..de2744f29 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java +++ b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java @@ -43,7 +43,7 @@ public class DictionaryDecayBroadcastReciever extends BroadcastReceiver { /** * Interval to update for decaying dictionaries. */ - private static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60); + /* package */ static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60); public static void setUpIntervalAlarmForDictionaryDecaying(Context context) { AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); @@ -60,7 +60,7 @@ public class DictionaryDecayBroadcastReciever extends BroadcastReceiver { public void onReceive(final Context context, final Intent intent) { final String action = intent.getAction(); if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) { - PersonalizationHelper.tryDecayingAllOpeningUserHistoryDictionary(); + PersonalizationHelper.runGCOnAllOpenedUserHistoryDictionaries(); } } } diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java index 5ae2fb6f8..385b525b6 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin.personalization; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.FileUtils; @@ -27,6 +28,7 @@ import java.io.FilenameFilter; import java.lang.ref.SoftReference; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; public class PersonalizationHelper { private static final String TAG = PersonalizationHelper.class.getSimpleName(); @@ -59,14 +61,35 @@ public class PersonalizationHelper { } } - public static void tryDecayingAllOpeningUserHistoryDictionary() { - for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry - : sLangUserHistoryDictCache.entrySet()) { - if (entry.getValue() != null) { - final UserHistoryDictionary dict = entry.getValue().get(); - if (dict != null) { - dict.decayIfNeeded(); - } + private static int sCurrentTimestampForTesting = 0; + public static void currentTimeChangedForTesting(final int currentTimestamp) { + if (TimeUnit.MILLISECONDS.toSeconds( + DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL) + < currentTimestamp - sCurrentTimestampForTesting) { + // TODO: Run GC for both PersonalizationDictionary and UserHistoryDictionary. + runGCOnAllOpenedUserHistoryDictionaries(); + } + } + + public static void runGCOnAllOpenedUserHistoryDictionaries() { + runGCOnAllDictionariesIfRequired(sLangUserHistoryDictCache); + } + + @UsedForTesting + public static void runGCOnAllOpenedPersonalizationDictionaries() { + runGCOnAllDictionariesIfRequired(sLangPersonalizationDictCache); + } + + private static <T extends DecayingExpandableBinaryDictionaryBase> + void runGCOnAllDictionariesIfRequired( + final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap) { + for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry + : dictionaryMap.entrySet()) { + final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get(); + if (dict != null) { + dict.runGCIfRequired(); + } else { + dictionaryMap.remove(entry.getKey()); } } } diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 8ea712835..afa8fe3a8 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -95,9 +95,9 @@ final class SuggestionStripLayoutHelper { private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); - private final int mSuggestionStripOption; + private final int mSuggestionStripOptions; // These constants are the flag values of - // {@link R.styleable#SuggestionStripView_suggestionStripOption} attribute. + // {@link R.styleable#SuggestionStripView_suggestionStripOptions} attribute. private static final int AUTO_CORRECT_BOLD = 0x01; private static final int AUTO_CORRECT_UNDERLINE = 0x02; private static final int VALID_TYPED_WORD_BOLD = 0x04; @@ -122,8 +122,8 @@ final class SuggestionStripLayoutHelper { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SuggestionStripView, defStyle, R.style.SuggestionStripView); - mSuggestionStripOption = a.getInt( - R.styleable.SuggestionStripView_suggestionStripOption, 0); + mSuggestionStripOptions = a.getInt( + R.styleable.SuggestionStripView_suggestionStripOptions, 0); mAlphaObsoleted = ResourceUtils.getFraction(a, R.styleable.SuggestionStripView_alphaObsoleted, 1.0f); mColorValidTypedWord = a.getColor(R.styleable.SuggestionStripView_colorValidTypedWord, 0); @@ -200,22 +200,24 @@ final class SuggestionStripLayoutHelper { return null; } final String word = suggestedWords.getLabel(indexInSuggestedWords); - final boolean isAutoCorrect = indexInSuggestedWords == 1 - && suggestedWords.mWillAutoCorrect; - final boolean isTypedWordValid = indexInSuggestedWords == 0 - && suggestedWords.mTypedWordValid; - if (!isAutoCorrect && !isTypedWordValid) { + // TODO: don't use the index to decide whether this is the auto-correction/typed word, as + // this is brittle + final boolean isAutoCorrection = suggestedWords.mWillAutoCorrect + && indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION; + final boolean isTypedWordValid = suggestedWords.mTypedWordValid + && indexInSuggestedWords == SuggestedWords.INDEX_OF_TYPED_WORD; + if (!isAutoCorrection && !isTypedWordValid) { return word; } final int len = word.length(); final Spannable spannedWord = new SpannableString(word); - final int option = mSuggestionStripOption; - if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0) - || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) { + final int options = mSuggestionStripOptions; + if ((isAutoCorrection && (options & AUTO_CORRECT_BOLD) != 0) + || (isTypedWordValid && (options & VALID_TYPED_WORD_BOLD) != 0)) { spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } - if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) { + if (isAutoCorrection && (options & AUTO_CORRECT_UNDERLINE) != 0) { spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } return spannedWord; @@ -242,22 +244,23 @@ final class SuggestionStripLayoutHelper { return indexInSuggestedWords; } - private int getSuggestionTextColor(final int indexInSuggestedWords, - final SuggestedWords suggestedWords) { + private int getSuggestionTextColor(final SuggestedWords suggestedWords, + final int indexInSuggestedWords) { final int positionInStrip = getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords); - // TODO: Need to revisit this logic with bigram suggestions - final boolean isSuggested = (indexInSuggestedWords != SuggestedWords.INDEX_OF_TYPED_WORD); + // Use identity for strings, not #equals : it's the typed word if it's the same object + final boolean isTypedWord = + suggestedWords.getWord(indexInSuggestedWords) == suggestedWords.mTypedWord; final int color; if (positionInStrip == mCenterPositionInStrip && suggestedWords.mWillAutoCorrect) { color = mColorAutoCorrect; - } else if (positionInStrip == mCenterPositionInStrip && suggestedWords.mTypedWordValid) { + } else if (isTypedWord && suggestedWords.mTypedWordValid) { color = mColorValidTypedWord; - } else if (isSuggested) { - color = mColorSuggested; - } else { + } else if (isTypedWord) { color = mColorTypedWord; + } else { + color = mColorSuggested; } if (LatinImeLogger.sDBG && suggestedWords.size() > 1) { // If we auto-correct, then the autocorrection is in slot 0 and the typed word @@ -270,7 +273,7 @@ final class SuggestionStripLayoutHelper { } } - if (suggestedWords.mIsObsoleteSuggestions && isSuggested) { + if (suggestedWords.mIsObsoleteSuggestions && !isTypedWord) { return applyAlpha(color, mAlphaObsoleted); } return color; @@ -438,7 +441,7 @@ final class SuggestionStripLayoutHelper { // {@link SuggestionStripView#onClick(View)}. wordView.setTag(indexInSuggestedWords); wordView.setText(getStyledSuggestedWord(suggestedWords, indexInSuggestedWords)); - wordView.setTextColor(getSuggestionTextColor(positionInStrip, suggestedWords)); + wordView.setTextColor(getSuggestionTextColor(suggestedWords, indexInSuggestedWords)); if (SuggestionStripView.DBG) { mDebugInfoViews.get(positionInStrip).setText( suggestedWords.getDebugString(indexInSuggestedWords)); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java index 60f1c7a4e..52708455e 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java @@ -22,7 +22,6 @@ import com.android.inputmethod.latin.SuggestedWords; * An object that gives basic control of a suggestion strip and some info on it. */ public interface SuggestionStripViewAccessor { - public boolean hasSuggestionStripView(); public void showAddToDictionaryHint(final String word); public boolean isShowingAddToDictionaryHint(); public void dismissAddToDictionaryHint(); diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java new file mode 100644 index 000000000..ee9718ad3 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.utils; + +import com.android.inputmethod.annotations.UsedForTesting; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * Utilities to manage executors. + */ +public class ExecutorUtils { + private static final ConcurrentHashMap<String, PrioritizedSerialExecutor> + sExecutorMap = CollectionUtils.newConcurrentHashMap(); + /** + * Gets the executor for the given dictionary name. + */ + public static PrioritizedSerialExecutor getExecutor(final String dictName) { + PrioritizedSerialExecutor executor = sExecutorMap.get(dictName); + if (executor == null) { + synchronized(sExecutorMap) { + executor = new PrioritizedSerialExecutor(); + sExecutorMap.put(dictName, executor); + } + } + return executor; + } + + /** + * Shutdowns all executors and removes all executors from the executor map for testing. + */ + @UsedForTesting + public static void shutdownAllExecutors() { + synchronized(sExecutorMap) { + for (final PrioritizedSerialExecutor executor : sExecutorMap.values()) { + executor.shutdown(); + sExecutorMap.remove(executor); + } + } + } +} diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java index a1d641508..562ff9e8d 100644 --- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java +++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java @@ -37,9 +37,9 @@ public final class LanguageModelParam { // non-0. Thus, it's not meaningful to compare 10, 100, and so on. // TODO: Revise the logic in ForgettingCurveUtils in native code. private static final int UNIGRAM_PROBABILITY_FOR_VALID_WORD = 100; - private static final int UNIGRAM_PROBABILITY_FOR_OOV_WORD = 10; - private static final int BIGRAM_PROBABILITY_FOR_VALID_WORD = 0; - private static final int BIGRAM_PROBABILITY_FOR_OOV_WORD = 0; + private static final int UNIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY; + private static final int BIGRAM_PROBABILITY_FOR_VALID_WORD = 10; + private static final int BIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY; public final String mTargetWord; public final int[] mWord0; diff --git a/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp index e1b35340b..bc4ca8e9e 100644 --- a/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp +++ b/native/jni/src/suggest/core/layout/proximity_info_state_utils.cpp @@ -992,7 +992,16 @@ namespace latinime { } } if (character != NOT_AN_INDEX) { - codePointBuf[index] = proximityInfo->getCodePointOf(character); + const int codePoint = proximityInfo->getCodePointOf(character); + if (codePoint == NOT_A_CODE_POINT) { + AKLOGE("Key index(%d) is not found. Cannot construct most probable string", + character); + ASSERT(false); + // Make the length zero, which means most probable string won't be used. + index = 0; + break; + } + codePointBuf[index] = codePoint; index++; } sumLogProbability += minLogProbability; diff --git a/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h b/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h index 59748c80d..a8dab9fcd 100644 --- a/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h +++ b/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h @@ -44,8 +44,6 @@ class DictionaryHeaderStructurePolicy { virtual float getMultiWordCostMultiplier() const = 0; - virtual int getLastDecayedTime() const = 0; - virtual void readHeaderValueOrQuestionMark(const char *const key, int *outValue, int outValueSize) const = 0; diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp index cd2243025..5df2096a4 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp @@ -37,7 +37,8 @@ void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const out if (outProbability) { if (bigramEntry.hasHistoricalInfo()) { *outProbability = - ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo()); + ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo(), + mHeaderPolicy); } else { *outProbability = bigramEntry.getProbability(); } @@ -160,8 +161,8 @@ bool Ver4BigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(const i } } else if (bigramEntry.hasHistoricalInfo()) { const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave( - bigramEntry.getHistoricalInfo()); - if (ForgettingCurveUtils::needsToKeep(&historicalInfo)) { + bigramEntry.getHistoricalInfo(), mHeaderPolicy); + if (ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy)) { const BigramEntry updatedBigramEntry = bigramEntry.updateHistoricalInfoAndGetEntry(&historicalInfo); if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) { @@ -230,7 +231,8 @@ const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom( if (mHeaderPolicy->hasHistoricalInfoOfWords()) { const HistoricalInfo updatedHistoricalInfo = ForgettingCurveUtils::createUpdatedHistoricalInfo( - originalBigramEntry->getHistoricalInfo(), newProbability, timestamp); + originalBigramEntry->getHistoricalInfo(), newProbability, timestamp, + mHeaderPolicy); return originalBigramEntry->updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo); } else { return originalBigramEntry->updateProbabilityAndGetEntry(newProbability); diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp index 3ce57d910..7c7b05ca8 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp @@ -18,7 +18,7 @@ namespace latinime { -// Note that these are corresponding definitions in Java side in FormatSpec.FileHeader. +// Note that these are corresponding definitions in Java side in DictionaryHeader. const char *const HeaderPolicy::MULTIPLE_WORDS_DEMOTION_RATE_KEY = "MULTIPLE_WORDS_DEMOTION_RATE"; const char *const HeaderPolicy::REQUIRES_GERMAN_UMLAUT_PROCESSING_KEY = "REQUIRES_GERMAN_UMLAUT_PROCESSING"; @@ -33,8 +33,26 @@ const char *const HeaderPolicy::EXTENDED_REGION_SIZE_KEY = "EXTENDED_REGION_SIZE // count. const char *const HeaderPolicy::HAS_HISTORICAL_INFO_KEY = "HAS_HISTORICAL_INFO"; const char *const HeaderPolicy::LOCALE_KEY = "locale"; // match Java declaration +const char *const HeaderPolicy::FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY = + "FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP"; +const char *const HeaderPolicy::FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY = + "FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID"; +const char *const HeaderPolicy::FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY = + "FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS"; + +const char *const HeaderPolicy::MAX_UNIGRAM_COUNT_KEY = "MAX_UNIGRAM_COUNT"; +const char *const HeaderPolicy::MAX_BIGRAM_COUNT_KEY = "MAX_BIGRAM_COUNT"; + const int HeaderPolicy::DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE = 100; const float HeaderPolicy::MULTIPLE_WORD_COST_MULTIPLIER_SCALE = 100.0f; +const int HeaderPolicy::DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP = 4; +const int HeaderPolicy::DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID = 0; +// 4 days +const int HeaderPolicy::DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS = + 4 * 24 * 60 * 60; + +const int HeaderPolicy::DEFAULT_MAX_UNIGRAM_COUNT = 10000; +const int HeaderPolicy::DEFAULT_MAX_BIGRAM_COUNT = 10000; // Used for logging. Question mark is used to indicate that the key is not found. void HeaderPolicy::readHeaderValueOrQuestionMark(const char *const key, int *outValue, diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h index fc347618c..66824245e 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h @@ -52,7 +52,20 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy { mExtendedRegionSize(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap, EXTENDED_REGION_SIZE_KEY, 0 /* defaultValue */)), mHasHistoricalInfoOfWords(HeaderReadWriteUtils::readBoolAttributeValue( - &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)) {} + &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)), + mForgettingCurveOccurrencesToLevelUp(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY, + DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP)), + mForgettingCurveProbabilityValuesTableId(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY, + DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID)), + mForgettingCurveDurationToLevelDown(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY, + DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS)), + mMaxUnigramCount(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, MAX_UNIGRAM_COUNT_KEY, DEFAULT_MAX_UNIGRAM_COUNT)), + mMaxBigramCount(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, MAX_BIGRAM_COUNT_KEY, DEFAULT_MAX_BIGRAM_COUNT)) {} // Constructs header information using an attribute map. HeaderPolicy(const FormatUtils::FORMAT_VERSION dictFormatVersion, @@ -71,8 +84,20 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy { DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)), mUnigramCount(0), mBigramCount(0), mExtendedRegionSize(0), mHasHistoricalInfoOfWords(HeaderReadWriteUtils::readBoolAttributeValue( - &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)) { - } + &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)), + mForgettingCurveOccurrencesToLevelUp(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY, + DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP)), + mForgettingCurveProbabilityValuesTableId(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY, + DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID)), + mForgettingCurveDurationToLevelDown(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY, + DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS)), + mMaxUnigramCount(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, MAX_UNIGRAM_COUNT_KEY, DEFAULT_MAX_UNIGRAM_COUNT)), + mMaxBigramCount(HeaderReadWriteUtils::readIntAttributeValue( + &mAttributeMap, MAX_BIGRAM_COUNT_KEY, DEFAULT_MAX_BIGRAM_COUNT)) {} // Temporary dummy header. HeaderPolicy() @@ -80,7 +105,9 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy { mAttributeMap(), mLocale(CharUtils::EMPTY_STRING), mMultiWordCostMultiplier(0.0f), mRequiresGermanUmlautProcessing(false), mIsDecayingDict(false), mDate(0), mLastDecayedTime(0), mUnigramCount(0), mBigramCount(0), - mExtendedRegionSize(0), mHasHistoricalInfoOfWords(false) {} + mExtendedRegionSize(0), mHasHistoricalInfoOfWords(false), + mForgettingCurveOccurrencesToLevelUp(0), mForgettingCurveProbabilityValuesTableId(0), + mForgettingCurveDurationToLevelDown(0), mMaxUnigramCount(0), mMaxBigramCount(0) {} ~HeaderPolicy() {} @@ -159,6 +186,26 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy { return &mAttributeMap; } + AK_FORCE_INLINE int getForgettingCurveOccurrencesToLevelUp() const { + return mForgettingCurveOccurrencesToLevelUp; + } + + AK_FORCE_INLINE int getForgettingCurveProbabilityValuesTableId() const { + return mForgettingCurveProbabilityValuesTableId; + } + + AK_FORCE_INLINE int getForgettingCurveDurationToLevelDown() const { + return mForgettingCurveDurationToLevelDown; + } + + AK_FORCE_INLINE int getMaxUnigramCount() const { + return mMaxUnigramCount; + } + + AK_FORCE_INLINE int getMaxBigramCount() const { + return mMaxBigramCount; + } + void readHeaderValueOrQuestionMark(const char *const key, int *outValue, int outValueSize) const; @@ -183,8 +230,18 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy { static const char *const EXTENDED_REGION_SIZE_KEY; static const char *const HAS_HISTORICAL_INFO_KEY; static const char *const LOCALE_KEY; + static const char *const FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY; + static const char *const FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY; + static const char *const FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY; + static const char *const MAX_UNIGRAM_COUNT_KEY; + static const char *const MAX_BIGRAM_COUNT_KEY; static const int DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE; static const float MULTIPLE_WORD_COST_MULTIPLIER_SCALE; + static const int DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP; + static const int DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID; + static const int DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS; + static const int DEFAULT_MAX_UNIGRAM_COUNT; + static const int DEFAULT_MAX_BIGRAM_COUNT; const FormatUtils::FORMAT_VERSION mDictFormatVersion; const HeaderReadWriteUtils::DictionaryFlags mDictionaryFlags; @@ -200,6 +257,11 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy { const int mBigramCount; const int mExtendedRegionSize; const bool mHasHistoricalInfoOfWords; + const int mForgettingCurveOccurrencesToLevelUp; + const int mForgettingCurveProbabilityValuesTableId; + const int mForgettingCurveDurationToLevelDown; + const int mMaxUnigramCount; + const int mMaxBigramCount; const std::vector<int> readLocale() const; float readMultipleWordCostMultiplier() const; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp index cb9d450ec..279f5b33a 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp @@ -23,6 +23,13 @@ namespace latinime { const BigramEntry BigramDictContent::getBigramEntryAndAdvancePosition( int *const bigramEntryPos) const { const BufferWithExtendableBuffer *const bigramListBuffer = getContentBuffer(); + if (*bigramEntryPos < 0 || *bigramEntryPos >= bigramListBuffer->getTailPosition()) { + AKLOGE("Invalid bigram entry position. bigramEntryPos: %d, bufSize: %d", + *bigramEntryPos, bigramListBuffer->getTailPosition()); + ASSERT(false); + return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY, + Ver4DictConstants::NOT_A_TERMINAL_ID); + } const int bigramFlags = bigramListBuffer->readUintAndAdvancePosition( Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos); const bool hasNext = (bigramFlags & Ver4DictConstants::BIGRAM_HAS_NEXT_MASK) != 0; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp index 29972a4e8..64d7bc0a5 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp @@ -24,6 +24,19 @@ void ShortcutDictContent::getShortcutEntryAndAdvancePosition(const int maxCodePo int *const outCodePoint, int *const outCodePointCount, int *const outProbability, bool *const outhasNext, int *const shortcutEntryPos) const { const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer(); + if (*shortcutEntryPos < 0 || *shortcutEntryPos >= shortcutListBuffer->getTailPosition()) { + AKLOGE("Invalid shortcut entry position. shortcutEntryPos: %d, bufSize: %d", + *shortcutEntryPos, shortcutListBuffer->getTailPosition()); + ASSERT(false); + if (outhasNext) { + *outhasNext = false; + } + if (outCodePointCount) { + *outCodePointCount = 0; + } + return; + } + const int shortcutFlags = shortcutListBuffer->readUintAndAdvancePosition( Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos); if (outProbability) { diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp index 17fc9483b..f149781f4 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp @@ -65,7 +65,7 @@ const PtNodeParams Ver4PatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProce mProbabilityDictContent->getProbabilityEntry(terminalId); if (probabilityEntry.hasHistoricalInfo()) { probability = ForgettingCurveUtils::decodeProbability( - probabilityEntry.getHistoricalInfo()); + probabilityEntry.getHistoricalInfo(), mHeaderPolicy); } else { probability = probabilityEntry.getProbability(); } diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h index 9d932457c..1db9ea026 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h @@ -26,6 +26,7 @@ namespace latinime { class BufferWithExtendableBuffer; +class HeaderPolicy; class ProbabilityDictContent; /* @@ -35,8 +36,10 @@ class ProbabilityDictContent; class Ver4PatriciaTrieNodeReader : public PtNodeReader { public: Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer, - const ProbabilityDictContent *const probabilityDictContent) - : mBuffer(buffer), mProbabilityDictContent(probabilityDictContent) {} + const ProbabilityDictContent *const probabilityDictContent, + const HeaderPolicy *const headerPolicy) + : mBuffer(buffer), mProbabilityDictContent(probabilityDictContent), + mHeaderPolicy(headerPolicy) {} ~Ver4PatriciaTrieNodeReader() {} @@ -50,6 +53,7 @@ class Ver4PatriciaTrieNodeReader : public PtNodeReader { const BufferWithExtendableBuffer *const mBuffer; const ProbabilityDictContent *const mProbabilityDictContent; + const HeaderPolicy *const mHeaderPolicy; const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos, const int siblingNodePos) const; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp index 32576cf0a..f24c2e1af 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp @@ -159,7 +159,7 @@ bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeA toBeUpdatedPtNodeParams->getTerminalId()); if (originalProbabilityEntry.hasHistoricalInfo()) { const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave( - originalProbabilityEntry.getHistoricalInfo()); + originalProbabilityEntry.getHistoricalInfo(), mHeaderPolicy); const ProbabilityEntry probabilityEntry = originalProbabilityEntry.createEntryWithUpdatedHistoricalInfo(&historicalInfo); if (!mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry( @@ -168,7 +168,7 @@ bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeA toBeUpdatedPtNodeParams->getTerminalId()); return false; } - const bool isValid = ForgettingCurveUtils::needsToKeep(&historicalInfo); + const bool isValid = ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy); if (!isValid) { if (!markPtNodeAsWillBecomeNonTerminal(toBeUpdatedPtNodeParams)) { AKLOGE("Cannot mark PtNode as willBecomeNonTerminal."); @@ -382,10 +382,11 @@ const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom( const ProbabilityEntry *const originalProbabilityEntry, const int newProbability, const int timestamp) const { // TODO: Consolidate historical info and probability. - if (mBuffers->getHeaderPolicy()->hasHistoricalInfoOfWords()) { + if (mHeaderPolicy->hasHistoricalInfoOfWords()) { const HistoricalInfo updatedHistoricalInfo = ForgettingCurveUtils::createUpdatedHistoricalInfo( - originalProbabilityEntry->getHistoricalInfo(), newProbability, timestamp); + originalProbabilityEntry->getHistoricalInfo(), newProbability, timestamp, + mHeaderPolicy); return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo( &updatedHistoricalInfo); } else { diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h index 66845bbd6..f01b3af0e 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h @@ -28,6 +28,7 @@ namespace latinime { class BufferWithExtendableBuffer; +class HeaderPolicy; class Ver4BigramListPolicy; class Ver4DictBuffers; class Ver4PatriciaTrieNodeReader; @@ -40,10 +41,11 @@ class Ver4ShortcutListPolicy; class Ver4PatriciaTrieNodeWriter : public PtNodeWriter { public: Ver4PatriciaTrieNodeWriter(BufferWithExtendableBuffer *const trieBuffer, - Ver4DictBuffers *const buffers, const PtNodeReader *const ptNodeReader, + Ver4DictBuffers *const buffers, const HeaderPolicy *const headerPolicy, + const PtNodeReader *const ptNodeReader, const PtNodeArrayReader *const ptNodeArrayReader, Ver4BigramListPolicy *const bigramPolicy, Ver4ShortcutListPolicy *const shortcutPolicy) - : mTrieBuffer(trieBuffer), mBuffers(buffers), + : mTrieBuffer(trieBuffer), mBuffers(buffers), mHeaderPolicy(headerPolicy), mReadingHelper(ptNodeReader, ptNodeArrayReader), mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy) {} @@ -116,6 +118,7 @@ class Ver4PatriciaTrieNodeWriter : public PtNodeWriter { BufferWithExtendableBuffer *const mTrieBuffer; Ver4DictBuffers *const mBuffers; + const HeaderPolicy *const mHeaderPolicy; DynamicPtReadingHelper mReadingHelper; Ver4BigramListPolicy *const mBigramPolicy; Ver4ShortcutListPolicy *const mShortcutPolicy; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp index b5d80be1d..4d1b0dadb 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp @@ -329,11 +329,15 @@ void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int quer snprintf(outResult, maxResultLength, "%d", mBigramCount); } else if (strncmp(query, MAX_UNIGRAM_COUNT_QUERY, compareLength) == 0) { snprintf(outResult, maxResultLength, "%d", - mHeaderPolicy->isDecayingDict() ? ForgettingCurveUtils::MAX_UNIGRAM_COUNT : + mHeaderPolicy->isDecayingDict() ? + ForgettingCurveUtils::getUnigramCountHardLimit( + mHeaderPolicy->getMaxUnigramCount()) : static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE)); } else if (strncmp(query, MAX_BIGRAM_COUNT_QUERY, compareLength) == 0) { snprintf(outResult, maxResultLength, "%d", - mHeaderPolicy->isDecayingDict() ? ForgettingCurveUtils::MAX_BIGRAM_COUNT : + mHeaderPolicy->isDecayingDict() ? + ForgettingCurveUtils::getBigramCountHardLimit( + mHeaderPolicy->getMaxBigramCount()) : static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE)); } } @@ -382,7 +386,8 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code bigramWord1CodePoints + codePointCount); const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo(); const int probability = bigramEntry.hasHistoricalInfo() ? - ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo()) : + ForgettingCurveUtils::decodeProbability( + bigramEntry.getHistoricalInfo(), mHeaderPolicy) : bigramEntry.getProbability(); bigrams.push_back(WordProperty::BigramProperty(&word1, probability, historicalInfo->getTimeStamp(), historicalInfo->getLevel(), diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h index 7796e2ddc..639c153a1 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h @@ -47,10 +47,10 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { mBuffers.get()->getTerminalPositionLookupTable(), mHeaderPolicy), mShortcutPolicy(mBuffers.get()->getMutableShortcutDictContent(), mBuffers.get()->getTerminalPositionLookupTable()), - mNodeReader(mDictBuffer, mBuffers.get()->getProbabilityDictContent()), + mNodeReader(mDictBuffer, mBuffers.get()->getProbabilityDictContent(), mHeaderPolicy), mPtNodeArrayReader(mDictBuffer), - mNodeWriter(mDictBuffer, mBuffers.get(), &mNodeReader, &mPtNodeArrayReader, - &mBigramPolicy, &mShortcutPolicy), + mNodeWriter(mDictBuffer, mBuffers.get(), mHeaderPolicy, &mNodeReader, + &mPtNodeArrayReader, &mBigramPolicy, &mShortcutPolicy), mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter), mWritingHelper(mBuffers.get()), mUnigramCount(mHeaderPolicy->getUnigramCount()), diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp index 93053c38d..3907c84a0 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp @@ -74,14 +74,15 @@ bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy, Ver4DictBuffers *const buffersToWrite, int *const outUnigramCount, int *const outBigramCount) { Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer(), - mBuffers->getProbabilityDictContent()); + mBuffers->getProbabilityDictContent(), headerPolicy); Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer()); Ver4BigramListPolicy bigramPolicy(mBuffers->getMutableBigramDictContent(), mBuffers->getTerminalPositionLookupTable(), headerPolicy); Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(), mBuffers->getTerminalPositionLookupTable()); Ver4PatriciaTrieNodeWriter ptNodeWriter(mBuffers->getWritableTrieBuffer(), - mBuffers, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy, &shortcutPolicy); + mBuffers, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy, + &shortcutPolicy); DynamicPtReadingHelper readingHelper(&ptNodeReader, &ptNodeArrayReader); readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); @@ -95,12 +96,11 @@ bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos, } const int unigramCount = traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted .getValidUnigramCount(); - if (headerPolicy->isDecayingDict() - && unigramCount > ForgettingCurveUtils::MAX_UNIGRAM_COUNT_AFTER_GC) { - if (!truncateUnigrams(&ptNodeReader, &ptNodeWriter, - ForgettingCurveUtils::MAX_UNIGRAM_COUNT_AFTER_GC)) { + const int maxUnigramCount = headerPolicy->getMaxUnigramCount(); + if (headerPolicy->isDecayingDict() && unigramCount > maxUnigramCount) { + if (!truncateUnigrams(&ptNodeReader, &ptNodeWriter, maxUnigramCount)) { AKLOGE("Cannot remove unigrams. current: %d, max: %d", unigramCount, - ForgettingCurveUtils::MAX_UNIGRAM_COUNT_AFTER_GC); + maxUnigramCount); return false; } } @@ -113,11 +113,10 @@ bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos, return false; } const int bigramCount = traversePolicyToUpdateBigramProbability.getValidBigramEntryCount(); - if (headerPolicy->isDecayingDict() - && bigramCount > ForgettingCurveUtils::MAX_BIGRAM_COUNT_AFTER_GC) { - if (!truncateBigrams(ForgettingCurveUtils::MAX_BIGRAM_COUNT_AFTER_GC)) { - AKLOGE("Cannot remove bigrams. current: %d, max: %d", bigramCount, - ForgettingCurveUtils::MAX_BIGRAM_COUNT_AFTER_GC); + const int maxBigramCount = headerPolicy->getMaxBigramCount(); + if (headerPolicy->isDecayingDict() && bigramCount > maxBigramCount) { + if (!truncateBigrams(maxBigramCount)) { + AKLOGE("Cannot remove bigrams. current: %d, max: %d", bigramCount, maxBigramCount); return false; } } @@ -126,7 +125,8 @@ bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos, PtNodeWriter::DictPositionRelocationMap dictPositionRelocationMap; readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); Ver4PatriciaTrieNodeWriter ptNodeWriterForNewBuffers(buffersToWrite->getWritableTrieBuffer(), - buffersToWrite, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy, &shortcutPolicy); + buffersToWrite, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy, + &shortcutPolicy); DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&ptNodeWriterForNewBuffers, buffersToWrite->getWritableTrieBuffer(), &dictPositionRelocationMap); @@ -137,14 +137,14 @@ bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos, // Create policy instances for the GCed dictionary. Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer(), - buffersToWrite->getProbabilityDictContent()); + buffersToWrite->getProbabilityDictContent(), headerPolicy); Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer()); Ver4BigramListPolicy newBigramPolicy(buffersToWrite->getMutableBigramDictContent(), buffersToWrite->getTerminalPositionLookupTable(), headerPolicy); Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(), buffersToWrite->getTerminalPositionLookupTable()); Ver4PatriciaTrieNodeWriter newPtNodeWriter(buffersToWrite->getWritableTrieBuffer(), - buffersToWrite, &newPtNodeReader, &newPtNodeArrayreader, &newBigramPolicy, + buffersToWrite, headerPolicy, &newPtNodeReader, &newPtNodeArrayreader, &newBigramPolicy, &newShortcutPolicy); // Re-assign terminal IDs for valid terminal PtNodes. TerminalPositionLookupTable::TerminalIdMap terminalIdMap; @@ -202,8 +202,9 @@ bool Ver4PatriciaTrieWritingHelper::truncateUnigrams( const ProbabilityEntry probabilityEntry = mBuffers->getProbabilityDictContent()->getProbabilityEntry(i); const int probability = probabilityEntry.hasHistoricalInfo() ? - ForgettingCurveUtils::decodeProbability(probabilityEntry.getHistoricalInfo()) : - probabilityEntry.getProbability(); + ForgettingCurveUtils::decodeProbability( + probabilityEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) : + probabilityEntry.getProbability(); priorityQueue.push(DictProbability(terminalPos, probability, probabilityEntry.getHistoricalInfo()->getTimeStamp())); } @@ -245,8 +246,9 @@ bool Ver4PatriciaTrieWritingHelper::truncateBigrams(const int maxBigramCount) { continue; } const int probability = bigramEntry.hasHistoricalInfo() ? - ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo()) : - bigramEntry.getProbability(); + ForgettingCurveUtils::decodeProbability( + bigramEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) : + bigramEntry.getProbability(); priorityQueue.push(DictProbability(entryPos, probability, bigramEntry.getHistoricalInfo()->getTimeStamp())); } diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp index d58d25989..35e05d77a 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp @@ -19,33 +19,29 @@ #include <cmath> #include <stdlib.h> -#include "suggest/core/policy/dictionary_header_structure_policy.h" +#include "suggest/policyimpl/dictionary/header/header_policy.h" #include "suggest/policyimpl/dictionary/utils/probability_utils.h" #include "utils/time_keeper.h" namespace latinime { -const int ForgettingCurveUtils::MAX_UNIGRAM_COUNT = 12000; -const int ForgettingCurveUtils::MAX_UNIGRAM_COUNT_AFTER_GC = 10000; -const int ForgettingCurveUtils::MAX_BIGRAM_COUNT = 12000; -const int ForgettingCurveUtils::MAX_BIGRAM_COUNT_AFTER_GC = 10000; - -const int ForgettingCurveUtils::MAX_COMPUTED_PROBABILITY = 127; +const int ForgettingCurveUtils::MULTIPLIER_TWO_IN_PROBABILITY_SCALE = 8; const int ForgettingCurveUtils::DECAY_INTERVAL_SECONDS = 2 * 60 * 60; const int ForgettingCurveUtils::MAX_LEVEL = 3; -const int ForgettingCurveUtils::MAX_COUNT = 3; const int ForgettingCurveUtils::MIN_VALID_LEVEL = 1; -const int ForgettingCurveUtils::TIME_STEP_DURATION_IN_SECONDS = 6 * 60 * 60; const int ForgettingCurveUtils::MAX_ELAPSED_TIME_STEP_COUNT = 15; const int ForgettingCurveUtils::DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD = 14; +const float ForgettingCurveUtils::UNIGRAM_COUNT_HARD_LIMIT_WEIGHT = 1.2; +const float ForgettingCurveUtils::BIGRAM_COUNT_HARD_LIMIT_WEIGHT = 1.2; + const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityTable; // TODO: Revise the logic to decide the initial probability depending on the given probability. /* static */ const HistoricalInfo ForgettingCurveUtils::createUpdatedHistoricalInfo( const HistoricalInfo *const originalHistoricalInfo, - const int newProbability, const int timestamp) { + const int newProbability, const int timestamp, const HeaderPolicy *const headerPolicy) { if (newProbability != NOT_A_PROBABILITY && originalHistoricalInfo->getLevel() == 0) { return HistoricalInfo(timestamp, MIN_VALID_LEVEL /* level */, 0 /* count */); } else if (!originalHistoricalInfo->isValid()) { @@ -53,7 +49,7 @@ const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityT return HistoricalInfo(timestamp, 0 /* level */, 1 /* count */); } else { const int updatedCount = originalHistoricalInfo->getCount() + 1; - if (updatedCount > MAX_COUNT) { + if (updatedCount >= headerPolicy->getForgettingCurveOccurrencesToLevelUp()) { // The count exceeds the max value the level can be incremented. if (originalHistoricalInfo->getLevel() >= MAX_LEVEL) { // The level is already max. @@ -71,9 +67,11 @@ const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityT } /* static */ int ForgettingCurveUtils::decodeProbability( - const HistoricalInfo *const historicalInfo) { - const int elapsedTimeStepCount = getElapsedTimeStepCount(historicalInfo->getTimeStamp()); - return sProbabilityTable.getProbability(historicalInfo->getLevel(), + const HistoricalInfo *const historicalInfo, const HeaderPolicy *const headerPolicy) { + const int elapsedTimeStepCount = getElapsedTimeStepCount(historicalInfo->getTimeStamp(), + headerPolicy->getForgettingCurveDurationToLevelDown()); + return sProbabilityTable.getProbability( + headerPolicy->getForgettingCurveProbabilityValuesTableId(), historicalInfo->getLevel(), min(max(elapsedTimeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT)); } @@ -82,24 +80,31 @@ const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityT if (unigramProbability == NOT_A_PROBABILITY) { return NOT_A_PROBABILITY; } else if (bigramProbability == NOT_A_PROBABILITY) { - return min(backoff(unigramProbability), MAX_COMPUTED_PROBABILITY); + return min(backoff(unigramProbability), MAX_PROBABILITY); } else { - return min(max(unigramProbability, bigramProbability), MAX_COMPUTED_PROBABILITY); + // TODO: Investigate better way to handle bigram probability. + return min(max(unigramProbability, bigramProbability + MULTIPLIER_TWO_IN_PROBABILITY_SCALE), + MAX_PROBABILITY); } } -/* static */ bool ForgettingCurveUtils::needsToKeep(const HistoricalInfo *const historicalInfo) { +/* static */ bool ForgettingCurveUtils::needsToKeep(const HistoricalInfo *const historicalInfo, + const HeaderPolicy *const headerPolicy) { return historicalInfo->getLevel() > 0 - || getElapsedTimeStepCount(historicalInfo->getTimeStamp()) - < DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD; + || getElapsedTimeStepCount(historicalInfo->getTimeStamp(), + headerPolicy->getForgettingCurveDurationToLevelDown()) + < DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD; } /* static */ const HistoricalInfo ForgettingCurveUtils::createHistoricalInfoToSave( - const HistoricalInfo *const originalHistoricalInfo) { + const HistoricalInfo *const originalHistoricalInfo, + const HeaderPolicy *const headerPolicy) { if (originalHistoricalInfo->getTimeStamp() == NOT_A_TIMESTAMP) { return HistoricalInfo(); } - const int elapsedTimeStep = getElapsedTimeStepCount(originalHistoricalInfo->getTimeStamp()); + const int durationToLevelDownInSeconds = headerPolicy->getForgettingCurveDurationToLevelDown(); + const int elapsedTimeStep = getElapsedTimeStepCount( + originalHistoricalInfo->getTimeStamp(), durationToLevelDownInSeconds); if (elapsedTimeStep <= MAX_ELAPSED_TIME_STEP_COUNT) { // No need to update historical info. return *originalHistoricalInfo; @@ -108,19 +113,18 @@ const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityT const int maxLevelDownAmonut = elapsedTimeStep / (MAX_ELAPSED_TIME_STEP_COUNT + 1); const int levelDownAmount = (maxLevelDownAmonut >= originalHistoricalInfo->getLevel()) ? originalHistoricalInfo->getLevel() : maxLevelDownAmonut; - const int adjustedTimestamp = originalHistoricalInfo->getTimeStamp() + - levelDownAmount * (MAX_ELAPSED_TIME_STEP_COUNT + 1) * TIME_STEP_DURATION_IN_SECONDS; - return HistoricalInfo(adjustedTimestamp, + const int adjustedTimestampInSeconds = originalHistoricalInfo->getTimeStamp() + + levelDownAmount * durationToLevelDownInSeconds; + return HistoricalInfo(adjustedTimestampInSeconds, originalHistoricalInfo->getLevel() - levelDownAmount, 0 /* count */); } /* static */ bool ForgettingCurveUtils::needsToDecay(const bool mindsBlockByDecay, - const int unigramCount, const int bigramCount, - const DictionaryHeaderStructurePolicy *const headerPolicy) { - if (unigramCount >= ForgettingCurveUtils::MAX_UNIGRAM_COUNT) { + const int unigramCount, const int bigramCount, const HeaderPolicy *const headerPolicy) { + if (unigramCount >= getUnigramCountHardLimit(headerPolicy->getMaxUnigramCount())) { // Unigram count exceeds the limit. return true; - } else if (bigramCount >= ForgettingCurveUtils::MAX_BIGRAM_COUNT) { + } else if (bigramCount >= getBigramCountHardLimit(headerPolicy->getMaxBigramCount())) { // Bigram count exceeds the limit. return true; } @@ -137,37 +141,71 @@ const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityT // See comments in ProbabilityUtils::backoff(). /* static */ int ForgettingCurveUtils::backoff(const int unigramProbability) { - if (unigramProbability == NOT_A_PROBABILITY) { - return NOT_A_PROBABILITY; - } else { - return max(unigramProbability - 8, 0); - } + // See TODO comments in ForgettingCurveUtils::getProbability(). + return unigramProbability; } -/* static */ int ForgettingCurveUtils::getElapsedTimeStepCount(const int timestamp) { - return (TimeKeeper::peekCurrentTime() - timestamp) / TIME_STEP_DURATION_IN_SECONDS; +/* static */ int ForgettingCurveUtils::getElapsedTimeStepCount(const int timestamp, + const int durationToLevelDownInSeconds) { + const int elapsedTimeInSeconds = TimeKeeper::peekCurrentTime() - timestamp; + const int timeStepDurationInSeconds = + durationToLevelDownInSeconds / (MAX_ELAPSED_TIME_STEP_COUNT + 1); + return elapsedTimeInSeconds / timeStepDurationInSeconds; } -ForgettingCurveUtils::ProbabilityTable::ProbabilityTable() : mTable() { - mTable.resize(MAX_LEVEL + 1); - for (int level = 0; level <= MAX_LEVEL; ++level) { - mTable[level].resize(MAX_ELAPSED_TIME_STEP_COUNT + 1); - const float initialProbability = - static_cast<float>(MAX_COMPUTED_PROBABILITY / (1 << (MAX_LEVEL - level))); - for (int timeStepCount = 0; timeStepCount <= MAX_ELAPSED_TIME_STEP_COUNT; ++timeStepCount) { - if (level == 0) { - mTable[level][timeStepCount] = NOT_A_PROBABILITY; - continue; +const int ForgettingCurveUtils::ProbabilityTable::PROBABILITY_TABLE_COUNT = 4; +const int ForgettingCurveUtils::ProbabilityTable::WEAK_PROBABILITY_TABLE_ID = 0; +const int ForgettingCurveUtils::ProbabilityTable::MODEST_PROBABILITY_TABLE_ID = 1; +const int ForgettingCurveUtils::ProbabilityTable::STRONG_PROBABILITY_TABLE_ID = 2; +const int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_PROBABILITY_TABLE_ID = 3; +const int ForgettingCurveUtils::ProbabilityTable::WEAK_MAX_PROBABILITY = 127; +const int ForgettingCurveUtils::ProbabilityTable::MODEST_BASE_PROBABILITY = 32; +const int ForgettingCurveUtils::ProbabilityTable::STRONG_BASE_PROBABILITY = 35; +const int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_BASE_PROBABILITY = 40; + + +ForgettingCurveUtils::ProbabilityTable::ProbabilityTable() : mTables() { + mTables.resize(PROBABILITY_TABLE_COUNT); + for (int tableId = 0; tableId < PROBABILITY_TABLE_COUNT; ++tableId) { + mTables[tableId].resize(MAX_LEVEL + 1); + for (int level = 0; level <= MAX_LEVEL; ++level) { + mTables[tableId][level].resize(MAX_ELAPSED_TIME_STEP_COUNT + 1); + const float initialProbability = getBaseProbabilityForLevel(tableId, level); + const float endProbability = getBaseProbabilityForLevel(tableId, level - 1); + for (int timeStepCount = 0; timeStepCount <= MAX_ELAPSED_TIME_STEP_COUNT; + ++timeStepCount) { + if (level == 0) { + mTables[tableId][level][timeStepCount] = NOT_A_PROBABILITY; + continue; + } + const float probability = initialProbability + * powf(initialProbability / endProbability, + -1.0f * static_cast<float>(timeStepCount) + / static_cast<float>(MAX_ELAPSED_TIME_STEP_COUNT + 1)); + mTables[tableId][level][timeStepCount] = + min(max(static_cast<int>(probability), 1), MAX_PROBABILITY); } - const int elapsedTime = timeStepCount * TIME_STEP_DURATION_IN_SECONDS; - const float probability = initialProbability - * powf(2.0f, -1.0f * static_cast<float>(elapsedTime) - / static_cast<float>(TIME_STEP_DURATION_IN_SECONDS - * (MAX_ELAPSED_TIME_STEP_COUNT + 1))); - mTable[level][timeStepCount] = - min(max(static_cast<int>(probability), 1), MAX_COMPUTED_PROBABILITY); } } } +/* static */ int ForgettingCurveUtils::ProbabilityTable::getBaseProbabilityForLevel( + const int tableId, const int level) { + if (tableId == WEAK_PROBABILITY_TABLE_ID) { + // Max probability is 127. + return static_cast<float>(WEAK_MAX_PROBABILITY / (1 << (MAX_LEVEL - level))); + } else if (tableId == MODEST_PROBABILITY_TABLE_ID) { + // Max probability is 128. + return static_cast<float>(MODEST_BASE_PROBABILITY * (level + 1)); + } else if (tableId == STRONG_PROBABILITY_TABLE_ID) { + // Max probability is 140. + return static_cast<float>(STRONG_BASE_PROBABILITY * (level + 1)); + } else if (tableId == AGGRESSIVE_PROBABILITY_TABLE_ID) { + // Max probability is 160. + return static_cast<float>(AGGRESSIVE_BASE_PROBABILITY * (level + 1)); + } else { + return NOT_A_PROBABILITY; + } +} + } // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h index b37353455..bb8690939 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h @@ -24,31 +24,39 @@ namespace latinime { -class DictionaryHeaderStructurePolicy; +class HeaderPolicy; class ForgettingCurveUtils { public: - static const int MAX_UNIGRAM_COUNT; - static const int MAX_UNIGRAM_COUNT_AFTER_GC; - static const int MAX_BIGRAM_COUNT; - static const int MAX_BIGRAM_COUNT_AFTER_GC; - static const HistoricalInfo createUpdatedHistoricalInfo( const HistoricalInfo *const originalHistoricalInfo, const int newProbability, - const int timestamp); + const int timestamp, const HeaderPolicy *const headerPolicy); static const HistoricalInfo createHistoricalInfoToSave( - const HistoricalInfo *const originalHistoricalInfo); + const HistoricalInfo *const originalHistoricalInfo, + const HeaderPolicy *const headerPolicy); - static int decodeProbability(const HistoricalInfo *const historicalInfo); + static int decodeProbability(const HistoricalInfo *const historicalInfo, + const HeaderPolicy *const headerPolicy); static int getProbability(const int encodedUnigramProbability, const int encodedBigramProbability); - static bool needsToKeep(const HistoricalInfo *const historicalInfo); + static bool needsToKeep(const HistoricalInfo *const historicalInfo, + const HeaderPolicy *const headerPolicy); static bool needsToDecay(const bool mindsBlockByDecay, const int unigramCount, - const int bigramCount, const DictionaryHeaderStructurePolicy *const headerPolicy); + const int bigramCount, const HeaderPolicy *const headerPolicy); + + AK_FORCE_INLINE static int getUnigramCountHardLimit(const int maxUnigramCount) { + return static_cast<int>(static_cast<float>(maxUnigramCount) + * UNIGRAM_COUNT_HARD_LIMIT_WEIGHT); + } + + AK_FORCE_INLINE static int getBigramCountHardLimit(const int maxBigramCount) { + return static_cast<int>(static_cast<float>(maxBigramCount) + * BIGRAM_COUNT_HARD_LIMIT_WEIGHT); + } private: DISALLOW_IMPLICIT_CONSTRUCTORS(ForgettingCurveUtils); @@ -57,32 +65,46 @@ class ForgettingCurveUtils { public: ProbabilityTable(); - int getProbability(const int level, const int elapsedTimeStepCount) const { - return mTable[level][elapsedTimeStepCount]; + int getProbability(const int tableId, const int level, + const int elapsedTimeStepCount) const { + return mTables[tableId][level][elapsedTimeStepCount]; } private: DISALLOW_COPY_AND_ASSIGN(ProbabilityTable); - std::vector<std::vector<int> > mTable; + static const int PROBABILITY_TABLE_COUNT; + static const int WEAK_PROBABILITY_TABLE_ID; + static const int MODEST_PROBABILITY_TABLE_ID; + static const int STRONG_PROBABILITY_TABLE_ID; + static const int AGGRESSIVE_PROBABILITY_TABLE_ID; + + static const int WEAK_MAX_PROBABILITY; + static const int MODEST_BASE_PROBABILITY; + static const int STRONG_BASE_PROBABILITY; + static const int AGGRESSIVE_BASE_PROBABILITY; + + std::vector<std::vector<std::vector<int> > > mTables; + + static int getBaseProbabilityForLevel(const int tableId, const int level); }; - static const int MAX_COMPUTED_PROBABILITY; + static const int MULTIPLIER_TWO_IN_PROBABILITY_SCALE; static const int DECAY_INTERVAL_SECONDS; static const int MAX_LEVEL; - static const int MAX_COUNT; static const int MIN_VALID_LEVEL; - static const int TIME_STEP_DURATION_IN_SECONDS; static const int MAX_ELAPSED_TIME_STEP_COUNT; static const int DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD; - static const int HALF_LIFE_TIME_IN_SECONDS; + + static const float UNIGRAM_COUNT_HARD_LIMIT_WEIGHT; + static const float BIGRAM_COUNT_HARD_LIMIT_WEIGHT; static const ProbabilityTable sProbabilityTable; static int backoff(const int unigramProbability); - static int getElapsedTimeStepCount(const int timestamp); + static int getElapsedTimeStepCount(const int timestamp, const int durationToLevelDown); }; } // namespace latinime #endif /* LATINIME_FORGETTING_CURVE_UTILS_H */ diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java new file mode 100644 index 000000000..9939a4335 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard; + +import android.content.Context; +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.ContextThemeWrapper; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; +import com.android.inputmethod.keyboard.KeyboardLayoutSet.Builder; +import com.android.inputmethod.keyboard.KeyboardSwitcher.KeyboardTheme; +import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.RichInputMethodManager; +import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils; +import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.ResourceUtils; +import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; + +import java.util.ArrayList; +import java.util.Locale; + +@SmallTest +public class KeyboardLayoutSetTestsBase extends AndroidTestCase { + private static final int NUMBER_OF_SUBTYPES = 63; + private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 40; + + private static final KeyboardTheme DEFAULT_KEYBOARD_THEME = + KeyboardSwitcher.KEYBOARD_THEMES[KeyboardSwitcher.THEME_INDEX_DEFAULT]; + + // All input method subtypes of LatinIME. + private final ArrayList<InputMethodSubtype> mAllSubtypesList = CollectionUtils.newArrayList(); + private final ArrayList<InputMethodSubtype> mAsciiCapableSubtypesList = + CollectionUtils.newArrayList(); + + private Context mThemeContext; + private int mScreenMetrics; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mScreenMetrics = mContext.getResources().getInteger(R.integer.config_screen_metrics); + + mThemeContext = new ContextThemeWrapper(mContext, DEFAULT_KEYBOARD_THEME.mStyleId); + RichInputMethodManager.init(mThemeContext); + final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); + + final InputMethodInfo imi = richImm.getInputMethodInfoOfThisIme(); + final int subtypeCount = imi.getSubtypeCount(); + for (int index = 0; index < subtypeCount; index++) { + final InputMethodSubtype subtype = imi.getSubtypeAt(index); + mAllSubtypesList.add(subtype); + if (InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)) { + mAsciiCapableSubtypesList.add(subtype); + } + } + } + + protected final boolean isPhone() { + return mScreenMetrics == Constants.SCREEN_METRICS_SMALL_PHONE + || mScreenMetrics == Constants.SCREEN_METRICS_LARGE_PHONE; + } + + private static String toString(final ArrayList<InputMethodSubtype> subtypeList) { + final StringBuilder sb = new StringBuilder(); + for (int index = 0; index < subtypeList.size(); index++) { + final InputMethodSubtype subtype = subtypeList.get(index); + sb.append((index + 1) + ": "); + sb.append(SubtypeLocaleUtils.getSubtypeNameForLogging(subtype)); + sb.append("\n"); + } + return sb.toString(); + } + + public final void testAllSubtypesCount() { + assertEquals(toString(mAllSubtypesList), + NUMBER_OF_SUBTYPES, mAllSubtypesList.size()); + } + + public final void testAsciiCapableSubtypesCount() { + assertEquals(toString(mAsciiCapableSubtypesList), + NUMBER_OF_ASCII_CAPABLE_SUBTYPES, mAsciiCapableSubtypesList.size()); + } + + protected final InputMethodSubtype getSubtype(final Locale locale, + final String keyboardLayout) { + for (final InputMethodSubtype subtype : mAllSubtypesList) { + final Locale subtypeLocale = SubtypeLocaleUtils.getSubtypeLocale(subtype); + final String subtypeLayout = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype); + if (locale.equals(subtypeLocale) && keyboardLayout.equals(subtypeLayout)) { + // Found subtype that matches locale and keyboard layout. + return subtype; + } + } + for (final InputMethodSubtype subtype : mAsciiCapableSubtypesList) { + final Locale subtypeLocale = SubtypeLocaleUtils.getSubtypeLocale(subtype); + if (locale.equals(subtypeLocale)) { + // Create additional subtype. + return AdditionalSubtypeUtils.createAdditionalSubtype( + locale.toString(), keyboardLayout, null /* extraValue */); + } + } + throw new RuntimeException( + "Unknown subtype: locale=" + locale + " keyboardLayout=" + keyboardLayout); + } + + protected final KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype, + final EditorInfo editorInfo) { + return createKeyboardLayoutSet(subtype, editorInfo, false /* isShortcutImeEnabled */, + false /* showsVoiceInputKey */, false /* isLanguageSwitchKeyEnabled */); + } + + protected final KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype, + final EditorInfo editorInfo, final boolean isShortcutImeEnabled, + final boolean showsVoiceInputKey, final boolean isLanguageSwitchKeyEnabled) { + final Context context = mThemeContext; + final Resources res = context.getResources(); + final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); + final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res); + final Builder builder = new Builder(context, editorInfo); + builder.setKeyboardGeometry(keyboardWidth, keyboardHeight) + .setSubtype(subtype) + .setOptions(isShortcutImeEnabled, showsVoiceInputKey, isLanguageSwitchKeyEnabled); + return builder.build(); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSetTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSetTests.java new file mode 100644 index 000000000..17d768718 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSetTests.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.content.Context; +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.latin.RichInputMethodManager; +import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.RunInLocale; +import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +@SmallTest +public final class KeyboardTextsSetTests extends AndroidTestCase { + // All input method subtypes of LatinIME. + private List<InputMethodSubtype> mAllSubtypesList; + + @Override + protected void setUp() throws Exception { + super.setUp(); + RichInputMethodManager.init(getContext()); + final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); + + final ArrayList<InputMethodSubtype> allSubtypesList = CollectionUtils.newArrayList(); + final InputMethodInfo imi = richImm.getInputMethodInfoOfThisIme(); + final int subtypeCount = imi.getSubtypeCount(); + for (int index = 0; index < subtypeCount; index++) { + final InputMethodSubtype subtype = imi.getSubtypeAt(index); + allSubtypesList.add(subtype); + } + mAllSubtypesList = Collections.unmodifiableList(allSubtypesList); + } + + // Test that the text {@link KeyboardTextsSet#SWITCH_TO_ALPHA_KEY_LABEL} exists for all + // subtypes. The text is needed to implement Emoji Keyboard, see + // {@link KeyboardSwitcher#setEmojiKeyboard()}. + public void testSwitchToAlphaKeyLabel() { + final KeyboardTextsSet textsSet = new KeyboardTextsSet(); + for (final InputMethodSubtype subtype : mAllSubtypesList) { + final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); + textsSet.setLocale(locale); + final String switchToAlphaKeyLabel = textsSet.getText( + KeyboardTextsSet.SWITCH_TO_ALPHA_KEY_LABEL); + assertNotNull("Switch to alpha key label of " + locale, switchToAlphaKeyLabel); + assertFalse("Switch to alpha key label of " + locale, switchToAlphaKeyLabel.isEmpty()); + } + } + + private static final String[] TEXT_NAMES_FROM_RESOURCE = { + // Labels for action. + "label_go_key", + "label_send_key", + "label_next_key", + "label_done_key", + "label_previous_key", + // Other labels. + "label_pause_key", + "label_wait_key", + }; + + // Test that the text from resources are correctly loaded for all subtypes. + public void testTextFromResources() { + final Context context = getContext(); + final KeyboardTextsSet textsSet = new KeyboardTextsSet(); + for (final InputMethodSubtype subtype : mAllSubtypesList) { + final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype); + textsSet.setLocale(locale); + final RunInLocale<Void> job = new RunInLocale<Void>() { + @Override + protected Void job(final Resources res) { + textsSet.loadStringResources(context); + return null; + } + }; + job.runInLocale(context.getResources(), locale); + for (final String name : TEXT_NAMES_FROM_RESOURCE) { + final String text = textsSet.getText(name); + assertNotNull(name + " of " + locale, text); + assertFalse(name + " of " + locale, text.isEmpty()); + } + } + } +} diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java index f4b16a7e1..fa5123665 100644 --- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java +++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java @@ -150,7 +150,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { binaryDictionary.flushWithGC(); binaryDictionary.close(); - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(dictFile); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(dictFile, 0, dictFile.length()); try { final FusionDictionary dict = dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */); diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java index e21e340c2..0ee0fb577 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java @@ -251,7 +251,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { FusionDictionary dict = null; try { - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, bufferType); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, 0, file.length(), + bufferType); now = System.currentTimeMillis(); dict = dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */); diff = System.currentTimeMillis() - now; @@ -413,7 +414,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { long now = -1, diff = -1; try { - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, bufferType); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, 0, file.length(), + bufferType); now = System.currentTimeMillis(); dictDecoder.readUnigramsAndBigramsBinary(resultWords, resultFreqs, resultBigrams); diff = System.currentTimeMillis() - now; @@ -537,7 +539,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { addBigrams(dict, words, bigrams); timeWritingDictToFile(file, dict, formatOptions); - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, DictDecoder.USE_BYTEARRAY); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, 0, file.length(), + DictDecoder.USE_BYTEARRAY); try { dictDecoder.openDictBuffer(); } catch (IOException e) { diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java index a85753e6b..9dc2b1058 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java @@ -68,7 +68,8 @@ public class Ver2DictDecoderTests extends AndroidTestCase { } assertNotNull(testFile); - final Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, factory); + final Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, 0, testFile.length(), + factory); try { dictDecoder.openDictBuffer(); } catch (Exception e) { @@ -110,7 +111,8 @@ public class Ver2DictDecoderTests extends AndroidTestCase { Log.e(TAG, "IOException while the creating temporary file", e); } - final Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, factory); + final Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, 0, testFile.length(), + factory); // the default return value of getBuffer() must be null. assertNull("the default return value of getBuffer() is not null", diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java index b1239f0af..6ace2de4f 100644 --- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java +++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java @@ -267,13 +267,13 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word)); } forcePassingShortTime(); - dict.decayIfNeeded(); + dict.runGCIfRequired(); dict.waitAllTasksForTests(); for (final String word : words) { assertTrue(dict.isInUnderlyingBinaryDictionaryForTests(word)); } forcePassingLongTime(); - dict.decayIfNeeded(); + dict.runGCIfRequired(); dict.waitAllTasksForTests(); for (final String word : words) { assertFalse(dict.isInUnderlyingBinaryDictionaryForTests(word)); diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java index d1df81b52..e31ac2ab6 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java @@ -192,7 +192,7 @@ public final class BinaryDictOffdeviceUtils { new BufferedInputStream(new FileInputStream(decodedSpec.mFile))); } else { final DictDecoder dictDecoder = FormatSpec.getDictDecoder(decodedSpec.mFile, - DictDecoder.USE_BYTEARRAY); + 0, decodedSpec.mFile.length(), DictDecoder.USE_BYTEARRAY); if (report) { System.out.println("Format : Binary dictionary format"); System.out.println("Packaging : " + decodedSpec.describeChain()); diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java index 80d71fc64..68d785044 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java @@ -264,7 +264,7 @@ public class DictionaryMaker { private static FusionDictionary readBinaryFile(final String binaryFilename) throws FileNotFoundException, IOException, UnsupportedFormatException { final File file = new File(binaryFilename); - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, 0, file.length()); return dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */); } diff --git a/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java new file mode 100644 index 000000000..a4ad6b514 --- /dev/null +++ b/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin.personalization; + +public class PersonalizationHelper { + public static void currentTimeChangedForTesting(final int currentTimestamp) { + } +} diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java index 7a4f6f7c5..faf00b4a5 100644 --- a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java +++ b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java @@ -77,7 +77,8 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase { assertEquals("Wrong decode spec", BinaryDictOffdeviceUtils.COMPRESSION, step); } assertEquals("Wrong decode spec", 3, decodeSpec.mDecoderSpec.size()); - final DictDecoder dictDecoder = FormatSpec.getDictDecoder(decodeSpec.mFile); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(decodeSpec.mFile, 0, + decodeSpec.mFile.length()); final FusionDictionary resultDict = dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */); assertEquals("Wrong version attribute", VERSION, resultDict.mOptions.mAttributes.get( diff --git a/tools/make-keyboard-text/res/values-af/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-af/donottranslate-more-keys.xml index ee96f442d..5a90e62bd 100644 --- a/tools/make-keyboard-text/res/values-af/donottranslate-more-keys.xml +++ b/tools/make-keyboard-text/res/values-af/donottranslate-more-keys.xml @@ -62,7 +62,6 @@ <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> <string name="more_keys_for_n">ñ,ń</string> - <string name="more_keys_for_y">ý,ŷ,ÿ,ij</string> <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE U+0133: "ij" LATIN SMALL LIGATURE IJ --> <string name="more_keys_for_y">ý,ij</string> |