diff options
156 files changed, 1234 insertions, 459 deletions
diff --git a/dictionaries/de_wordlist.combined.gz b/dictionaries/de_wordlist.combined.gz Binary files differindex 803211c01..92c95540c 100644 --- a/dictionaries/de_wordlist.combined.gz +++ b/dictionaries/de_wordlist.combined.gz diff --git a/dictionaries/en_GB_wordlist.combined.gz b/dictionaries/en_GB_wordlist.combined.gz Binary files differindex 1fa9b85ea..217660fc4 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 2e039ff05..8aed9c5e0 100644 --- a/dictionaries/en_US_wordlist.combined.gz +++ b/dictionaries/en_US_wordlist.combined.gz diff --git a/dictionaries/en_wordlist.combined.gz b/dictionaries/en_wordlist.combined.gz Binary files differindex e845346d6..7fe6618cf 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 3391e64b4..71e7309fc 100644 --- a/dictionaries/es_wordlist.combined.gz +++ b/dictionaries/es_wordlist.combined.gz diff --git a/dictionaries/fr_wordlist.combined.gz b/dictionaries/fr_wordlist.combined.gz Binary files differindex 1b9fd73f9..afe44a6d9 100644 --- a/dictionaries/fr_wordlist.combined.gz +++ b/dictionaries/fr_wordlist.combined.gz diff --git a/dictionaries/it_wordlist.combined.gz b/dictionaries/it_wordlist.combined.gz Binary files differindex 5a5cbdc7a..ed58a12c5 100644 --- a/dictionaries/it_wordlist.combined.gz +++ b/dictionaries/it_wordlist.combined.gz diff --git a/dictionaries/nl_wordlist.combined.gz b/dictionaries/nl_wordlist.combined.gz Binary files differindex 37ba8ab42..19c3a7ea8 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 ba71a5581..2b84eecfd 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 02df1c1ee..7aac61e50 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 bcd50ab03..5bf9a60e8 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 401ad08b0..5e9266221 100644 --- a/dictionaries/ru_wordlist.combined.gz +++ b/dictionaries/ru_wordlist.combined.gz diff --git a/dictionaries/sv_wordlist.combined.gz b/dictionaries/sv_wordlist.combined.gz Binary files differindex b6ebab320..db44ae4c4 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 306cea184..d3c8825b9 100644 --- a/dictionaries/tr_wordlist.combined.gz +++ b/dictionaries/tr_wordlist.combined.gz diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict Binary files differindex 45b288375..c3c2cbe46 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 5bbb85761..b9e5bc77b 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 fae131850..076d5aa8f 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 19532d9bf..0e8686092 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 ff11b9798..609ef13b7 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 9fa50442a..c33865187 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 76b5f805a..d0af70730 100644 --- a/java/res/raw/main_ru.dict +++ b/java/res/raw/main_ru.dict diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml index cbdf434fa..ca8b816f4 100644 --- a/java/res/values-af/strings.xml +++ b/java/res/values-af/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serwies (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisioneel)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Geen taal nie (alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml index 1ac1f8cbf..9beccdf18 100644 --- a/java/res/values-am/strings.xml +++ b/java/res/values-am/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ሂንግሊሽ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ሰርቢያኛ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ተለምዷዊ)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (እስግ)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"ምንም ቋንቋ (ፊደላት)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ፊደላት (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ፊደላት (QWERTZ)"</string> diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml index dbab0efe8..62d5f3dbd 100644 --- a/java/res/values-ar/strings.xml +++ b/java/res/values-ar/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"هنجليزية (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"الصربية (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (التقليدية)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"بدون لغة (أبجدية)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"الأبجدية (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"الأبجدية (QWERTZ)"</string> diff --git a/java/res/values-az-rAZ/strings.xml b/java/res/values-az-rAZ/strings.xml index 463faf505..b13c90536 100644 --- a/java/res/values-az-rAZ/strings.xml +++ b/java/res/values-az-rAZ/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hingilis (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serb (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Ənənəvi)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Dil yoxdur (Əlifba)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Əlifba (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Əlifba (QWERTZ)"</string> diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml index 21df08466..805014b05 100644 --- a/java/res/values-bg/strings.xml +++ b/java/res/values-bg/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Сръбска (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционна клавиатура)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Без език (латиница)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Латиница (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Латиница (QWERTZ)"</string> diff --git a/java/res/values-bn-rBD/strings.xml b/java/res/values-bn-rBD/strings.xml index edd3b57d2..5487bb5f2 100644 --- a/java/res/values-bn-rBD/strings.xml +++ b/java/res/values-bn-rBD/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"হিংলিশ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"সার্বিয়ান (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ঐতিহ্যবাহি)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"কোনো ভাষা নয় (বর্ণমালা)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"বর্ণমালা (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"বর্ণমালা (QWERTZ)"</string> diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml index 17615e538..ef792b8d0 100644 --- a/java/res/values-ca/strings.xml +++ b/java/res/values-ca/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbi (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Cap idioma (alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml index 996bc7012..4fd0e71e1 100644 --- a/java/res/values-cs/strings.xml +++ b/java/res/values-cs/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"srbština (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradiční)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktní)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Žádný jazyk (latinka)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Latinka (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Latinka (QWERTZ)"</string> diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index fe1820b96..0e92e4711 100644 --- a/java/res/values-da/strings.xml +++ b/java/res/values-da/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbisk (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionelt)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Intet sprog (Alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml index 13c012565..1ced6d099 100644 --- a/java/res/values-de/strings.xml +++ b/java/res/values-de/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbisch (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionell)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Keine Sprache (lat. Alphabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Lat. Alphabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Lat. Alphabet (QWERTZ)"</string> diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml index f4f58e115..d9c4a40f0 100644 --- a/java/res/values-el/strings.xml +++ b/java/res/values-el/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Σερβικά (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Παραδοσιακά)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Συμπαγές)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Καμία γλώσσα (Αλφάβητο)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Αλφάβητο (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Αλφάβητο (QWERTZ)"</string> diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml index 249f8f30f..3ed282651 100644 --- a/java/res/values-en-rGB/strings.xml +++ b/java/res/values-en-rGB/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"No language (Alphabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet (QWERTZ)"</string> diff --git a/java/res/values-en-rIN/strings.xml b/java/res/values-en-rIN/strings.xml index 249f8f30f..3ed282651 100644 --- a/java/res/values-en-rIN/strings.xml +++ b/java/res/values-en-rIN/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"No language (Alphabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet (QWERTZ)"</string> diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml index f0aebbeb8..8142b1d0b 100644 --- a/java/res/values-es-rUS/strings.xml +++ b/java/res/values-es-rUS/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Ningún idioma (alfabeto)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string> diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml index a470bc9c5..a49ae31e8 100644 --- a/java/res/values-es/strings.xml +++ b/java/res/values-es/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacto)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Ningún idioma (alfabeto)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string> diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml index ffbaba047..440331e84 100644 --- a/java/res/values-et-rEE/strings.xml +++ b/java/res/values-et-rEE/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi-inglise (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditsiooniline)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktne)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Keel puudub (tähestik)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Tähestik (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Tähestik (QWERTZ)"</string> diff --git a/java/res/values-eu-rES/strings.xml b/java/res/values-eu-rES/strings.xml index f9d1dfd39..9496d95e9 100644 --- a/java/res/values-eu-rES/strings.xml +++ b/java/res/values-eu-rES/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglisha (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbiarra (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradizionala)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Ez dago hizkuntzarik (alfabetoa)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabetoa (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabetoa (QWERTZ)"</string> diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml index 31627844c..a0390dfdb 100644 --- a/java/res/values-fa/strings.xml +++ b/java/res/values-fa/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"هندی انگلیسی (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"صربی (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (سنتی)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"بدون زبان (حروف الفبا)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"حروف الفبا (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"حروف الفبا (QWERTZ)"</string> diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml index b8fcd8131..b133cc9d9 100644 --- a/java/res/values-fi/strings.xml +++ b/java/res/values-fi/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindienglanti (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"serbialainen (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (perinteinen)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Ei kieltä (aakkoset)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Aakkoset (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Aakkoset (QWERTZ)"</string> diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml index e5492a1a4..ee522059c 100644 --- a/java/res/values-fr-rCA/strings.xml +++ b/java/res/values-fr-rCA/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbe (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionnel)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Aucune langue (alphabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet latin (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet latin (QWERTZ)"</string> diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml index df6167cd1..2a93c992d 100644 --- a/java/res/values-fr/strings.xml +++ b/java/res/values-fr/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi/Anglais (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbe (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionnel)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Aucune langue (latin)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet latin (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet latin (QWERTZ)"</string> diff --git a/java/res/values-gl-rES/strings.xml b/java/res/values-gl-rES/strings.xml index 57979b6d4..d266ad5a6 100644 --- a/java/res/values-gl-rES/strings.xml +++ b/java/res/values-gl-rES/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Ningún idioma (alfabeto)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string> diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml index 3cf27b58c..9fc08ac8e 100644 --- a/java/res/values-hi/strings.xml +++ b/java/res/values-hi/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिंग्लिश (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"सर्बियाई (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (पारंपरिक)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"भाषा उपलब्ध नहीं है (लैटिन वर्णाक्षर)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"वर्णाक्षर (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"वर्णाक्षर (QWERTZ)"</string> diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml index b13a99734..7a5a665b3 100644 --- a/java/res/values-hr/strings.xml +++ b/java/res/values-hr/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Srpski (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionalni)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Nema jezika (abeceda)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abeceda (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abeceda (QWERTZ)"</string> diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml index 93099fee8..71314b0eb 100644 --- a/java/res/values-hu/strings.xml +++ b/java/res/values-hu/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (hindi-angol, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Szerb (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (hagyományos)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Nincs nyelv (ábécé)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Ábécé (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Ábécé (QWERTZ)"</string> diff --git a/java/res/values-hy-rAM/strings.xml b/java/res/values-hy-rAM/strings.xml index 920867df8..7d301195a 100644 --- a/java/res/values-hy-rAM/strings.xml +++ b/java/res/values-hy-rAM/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Հինգլիշ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Սերբերեն (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ավանդական)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Ոչ մի լեզվով (Այբուբեն)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Այբուբեն (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Այբուբեն (QWERTZ)"</string> diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml index 7381cd6fe..bd86f01b1 100644 --- a/java/res/values-in/strings.xml +++ b/java/res/values-in/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisional)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Rapat)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Tidak ada bahasa (Abjad)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abjad (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abjad (QWERTZ)"</string> diff --git a/java/res/values-is-rIS/strings.xml b/java/res/values-is-rIS/strings.xml index affa407d2..2bc3bfbeb 100644 --- a/java/res/values-is-rIS/strings.xml +++ b/java/res/values-is-rIS/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbneskt (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (hefðbundið)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Ekkert tungumál (stafróf)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Stafróf (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Stafróf (QWERTZ)"</string> diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml index 5572b2cde..2bca3b40b 100644 --- a/java/res/values-it/strings.xml +++ b/java/res/values-it/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbo (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradizionale)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compatto)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Nessuna lingua (alfabeto)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string> diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml index 468f7cb9d..c99d5123b 100644 --- a/java/res/values-iw/strings.xml +++ b/java/res/values-iw/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"אנגלית הודית (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"סרבית (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (מסורתית)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (קומפקטית)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"ללא שפה (אלף-בית)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"אלף-בית (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"אלף-בית (QWERTZ)"</string> diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml index 5ae8fcce4..4caaae394 100644 --- a/java/res/values-ja/strings.xml +++ b/java/res/values-ja/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ヒングリッシュ(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"セルビア語(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(伝統言語)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"言語なし(アルファベット)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"アルファベット(QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"アルファベット(QWERTZ)"</string> diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml index 4f221a937..dc2308c2e 100644 --- a/java/res/values-ka-rGE/strings.xml +++ b/java/res/values-ka-rGE/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ჰინგლისური (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"სერბული (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ტრადიციული)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"ენის გარეშე (ანბანი)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ანბანი (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ანბანი (QWERTZ)"</string> diff --git a/java/res/values-kk-rKZ/strings.xml b/java/res/values-kk-rKZ/strings.xml index e92b7c29d..838a07a77 100644 --- a/java/res/values-kk-rKZ/strings.xml +++ b/java/res/values-kk-rKZ/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Серб (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (дәстүрлі)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Тіл жоқ (әліпби)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Әліпби (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Әліпби (QWERTZ)"</string> diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml index f1a9ecbd0..8aea853a2 100644 --- a/java/res/values-km-rKH/strings.xml +++ b/java/res/values-km-rKH/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"សើប (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (អក្សរពេញ)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (បង្រួម)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"គ្មានភាសា (អក្សរក្រម)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"តាមលំដាប់អក្សរក្រម (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"តាមលំដាប់អក្សរក្រម (QWERTZ)"</string> diff --git a/java/res/values-kn-rIN/strings.xml b/java/res/values-kn-rIN/strings.xml index 02f8fecbd..04d9b1c49 100644 --- a/java/res/values-kn-rIN/strings.xml +++ b/java/res/values-kn-rIN/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ಹಿಂಗ್ಲಿಷ್ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ಸರ್ಬಿಯನ್ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಸಾಂಪ್ರದಾಯಿಕ)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಕಾಂಪ್ಯಾಕ್ಟ್)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"ಯಾವುದೇ ಭಾಷೆಯಿಲ್ಲ (ವರ್ಣಮಾಲೆ)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ವರ್ಣಮಾಲೆ (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ವರ್ಣಮಾಲೆ (QWERTZ)"</string> diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml index 1c4612009..e3935174e 100644 --- a/java/res/values-ko/strings.xml +++ b/java/res/values-ko/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"인도 영어(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"세르비아어(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(번체)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"언어 없음(알파벳)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"알파벳(QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"알파벳(QWERTZ)"</string> diff --git a/java/res/values-ky-rKG/strings.xml b/java/res/values-ky-rKG/strings.xml index 3fd906209..90c2db3b1 100644 --- a/java/res/values-ky-rKG/strings.xml +++ b/java/res/values-ky-rKG/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Сербче (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Салттык)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Тил жок (Алфавит)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Алфавит (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Алфавит (QWERTZ)"</string> diff --git a/java/res/values-lo-rLA/strings.xml b/java/res/values-lo-rLA/strings.xml index 55f97c32d..b23eb31b7 100644 --- a/java/res/values-lo-rLA/strings.xml +++ b/java/res/values-lo-rLA/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ຮິງລິສ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ເຊີບຽນ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ດັ້ງເດີມ)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"ບໍ່ມີພາສາ (ໂຕອັກສອນ)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ໂຕອັກສອນ (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ໂຕອັກສອນ (QWERTZ)"</string> diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml index d1782fa7f..cc8d0eaf6 100644 --- a/java/res/values-lt/strings.xml +++ b/java/res/values-lt/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi ir anglų derinys (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbų k. (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicinė)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktiška)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Kalbos nėra (abėcėlė)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abėcėlė (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abėcėlė (QWERTZ)"</string> diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml index 8de28bed6..ed7e9d457 100644 --- a/java/res/values-lv/strings.xml +++ b/java/res/values-lv/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi–angļu valoda (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbu (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionālā)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Nav valodas (alfabēts)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabēts (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabēts (QWERTZ)"</string> diff --git a/java/res/values-mk-rMK/strings.xml b/java/res/values-mk-rMK/strings.xml index e4ce6ec46..f3503f7bf 100644 --- a/java/res/values-mk-rMK/strings.xml +++ b/java/res/values-mk-rMK/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Српски (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционален)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Компактна)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Нема јазик (азбука)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Азбука (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Азбука (QWERTZ)"</string> diff --git a/java/res/values-ml-rIN/strings.xml b/java/res/values-ml-rIN/strings.xml index c5b399b55..acf00c2b6 100644 --- a/java/res/values-ml-rIN/strings.xml +++ b/java/res/values-ml-rIN/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ഹിംഗ്ലീഷ് (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"സെർബിയൻ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (പരമ്പരാഗതം)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"ഭാഷയില്ല (അക്ഷരമാല)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"അക്ഷരമാല (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"അക്ഷരമാല (QWERTZ)"</string> diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml index 4b1ef6280..938c90f29 100644 --- a/java/res/values-mn-rMN/strings.xml +++ b/java/res/values-mn-rMN/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Серьби хэл (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (уламжлалт)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Компакт)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Хэл байхгүй (Цагаан толгой)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Цагаан толгой (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Цагаан толгой (QWERTZ)"</string> diff --git a/java/res/values-mr-rIN/strings.xml b/java/res/values-mr-rIN/strings.xml index 7ebdd059c..492226a8c 100644 --- a/java/res/values-mr-rIN/strings.xml +++ b/java/res/values-mr-rIN/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिंग्लिश (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"सर्बियन (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (पारंपारिक)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"भाषा नाही (वर्णमाला)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"वर्णमाला (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"वर्णमाला (QWERTZ)"</string> diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml index 01781a47a..f33bdb4b3 100644 --- a/java/res/values-ms-rMY/strings.xml +++ b/java/res/values-ms-rMY/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Bahasa Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Tiada bahasa (Abjad)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abjad (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abjad (QWERTZ)"</string> diff --git a/java/res/values-my-rMM/strings.xml b/java/res/values-my-rMM/strings.xml index 2b5a4d421..3e5a491ea 100644 --- a/java/res/values-my-rMM/strings.xml +++ b/java/res/values-my-rMM/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ဟင်ဂလိပ် (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ဆားဘီယား (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ရိုးရာ)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"ဘာသာစကားမရှိ (ဗျည်းအက္ခရာ)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ဗျည်းအက္ခရာ (ကွာတီ)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ဗျည်းအက္ခရာ (ကွာတီ)"</string> diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index d69e1e991..849d7ab2d 100644 --- a/java/res/values-nb/strings.xml +++ b/java/res/values-nb/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbisk (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradisjonelt)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Ingen språk (alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-ne-rNP/strings.xml b/java/res/values-ne-rNP/strings.xml index 5afe6d19e..ec17c4e6f 100644 --- a/java/res/values-ne-rNP/strings.xml +++ b/java/res/values-ne-rNP/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिङ्लिस (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"सर्बियाई (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (परम्परागत)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"कुनै भाषा होइन (वर्णमाला)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"वर्णमाला (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"वर्णमाला (QWERTZ)"</string> diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml index d5406a8e9..d09db3f17 100644 --- a/java/res/values-nl/strings.xml +++ b/java/res/values-nl/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi-Engels (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Servisch (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditioneel)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compact)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Geen taal (alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml index 30e87bc28..39cf7422d 100644 --- a/java/res/values-pl/strings.xml +++ b/java/res/values-pl/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"serbski (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradycyjny)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktowa)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Bez języka (alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml index 512647ae6..e063cba31 100644 --- a/java/res/values-pt-rPT/strings.xml +++ b/java/res/values-pt-rPT/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sérvio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacto)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Sem idioma (alfabeto)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string> diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml index 73ff94ace..2e0cd3b55 100644 --- a/java/res/values-pt/strings.xml +++ b/java/res/values-pt/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Híndi-inglês (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sérvio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Nenhum idioma (alfabeto)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string> diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml index a87eeebf3..8e3ebf2bf 100644 --- a/java/res/values-ro/strings.xml +++ b/java/res/values-ro/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sârbă (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradițională)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Nicio limbă (alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml index 3aef94dfc..bd45c68a7 100644 --- a/java/res/values-ru/strings.xml +++ b/java/res/values-ru/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Сербский (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (классическая)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Язык не определен (латиница)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Латиница (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Латиница (QWERTZ)"</string> diff --git a/java/res/values-si-rLK/strings.xml b/java/res/values-si-rLK/strings.xml index 847b42369..2e5f3d9f4 100644 --- a/java/res/values-si-rLK/strings.xml +++ b/java/res/values-si-rLK/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"හින්ග්ලිෂ් (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"සර්බියානු (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (සාම්ප්රදායික)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"භාෂාවක් නැත (අකාරාදිය)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"අකාරාදිය (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"අකාරාදිය (QWERTZ)"</string> diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml index 01e05004b..80c91c89f 100644 --- a/java/res/values-sk/strings.xml +++ b/java/res/values-sk/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"srbčina (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradičná)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Žiadny jazyk (latinka)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Latinka (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Latinka (QWERTZ)"</string> diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml index 8872b5656..396334cdb 100644 --- a/java/res/values-sl/strings.xml +++ b/java/res/values-sl/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindujska angleščina (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Srbščina (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionalna)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Brez jezika (latinice)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Latinica (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Latinica (QWERTZ)"</string> diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml index 0d08933f6..28f6cae4e 100644 --- a/java/res/values-sr/strings.xml +++ b/java/res/values-sr/strings.xml @@ -95,13 +95,15 @@ <string name="subtype_en_US" msgid="6160452336634534239">"енглески (САД)"</string> <string name="subtype_es_US" msgid="5583145191430180200">"шпански (САД)"</string> <string name="subtype_hi_ZZ" msgid="8860448146262798623">"хенглески"</string> - <string name="subtype_sr_ZZ" msgid="9059219552986034343">"srpski"</string> + <string name="subtype_sr_ZZ" msgid="9059219552986034343">"српски (латиница)"</string> <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"енглески (УК) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"енглески (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_es_US" msgid="510930471167541338">"шпански (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"хенглески (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> - <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"srpski (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> + <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"српски (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционални)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Нема језика (абецеда)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Абецеда (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Абецеда (QWERTZ)"</string> diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index f3945a3ad..0c7d1a766 100644 --- a/java/res/values-sv/strings.xml +++ b/java/res/values-sv/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi/engelska (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbiska (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionell)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Inget språk (alfabet)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string> diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml index 10198ea0a..ae1a3a8f7 100644 --- a/java/res/values-sw/strings.xml +++ b/java/res/values-sw/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Kiserbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cha Jadi)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Hakuna lugha (Alfabeti)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeti (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeti (QWERTZ)"</string> diff --git a/java/res/values-ta-rIN/strings.xml b/java/res/values-ta-rIN/strings.xml index fc9f4a7a2..0a2d13890 100644 --- a/java/res/values-ta-rIN/strings.xml +++ b/java/res/values-ta-rIN/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ஹிங்கிலிஷ் (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"செர்பியன் (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (பாரம்பரியமானது)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"மொழியில்லை (அகரவரிசை)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"அகரவரிசை (க்வெர்டி)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"அகரவரிசை (க்வெர்ட்ச்)"</string> diff --git a/java/res/values-te-rIN/strings.xml b/java/res/values-te-rIN/strings.xml index c3d732c87..15e9aaf38 100644 --- a/java/res/values-te-rIN/strings.xml +++ b/java/res/values-te-rIN/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"హింగ్లీష్ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"సెర్బియన్ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (సాంప్రదాయకం)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"భాష లేదు (ఆల్ఫాబెట్)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ఆల్ఫాబెట్ (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ఆల్ఫాబెట్ (QWERTZ)"</string> diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml index 674c03b06..5c239dbd4 100644 --- a/java/res/values-th/strings.xml +++ b/java/res/values-th/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ภาษาอังกฤษผสมกับฮินดู (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"เซอร์เบีย (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ดั้งเดิม)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"ไม่มีภาษา (ตัวอักษรละติน)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ตัวอักษร (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ตัวอักษร (QWERTZ)"</string> diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml index 6fa06c913..8d755e42f 100644 --- a/java/res/values-tl/strings.xml +++ b/java/res/values-tl/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Walang wika (Alpabeto)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alpabeto (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alpabeto (QWERTZ)"</string> diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml index 5802d7960..86426fa1a 100644 --- a/java/res/values-tr/strings.xml +++ b/java/res/values-tr/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hingilizce (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sırpça (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Geleneksel)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Dil yok (Alfabe)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabe (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabe (QWERTZ)"</string> diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml index 639658d3e..33ab58497 100644 --- a/java/res/values-uk/strings.xml +++ b/java/res/values-uk/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хінґліш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"сербська (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиційна)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Стандартна (латиниця)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Латиниця (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Латиниця (QWERTZ)"</string> diff --git a/java/res/values-ur-rPK/strings.xml b/java/res/values-ur-rPK/strings.xml index fbe6626cd..f00e503e0 100644 --- a/java/res/values-ur-rPK/strings.xml +++ b/java/res/values-ur-rPK/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ہنگلش (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"سربیائی (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (روایتی)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"کوئی زبان نہیں (الفابیٹ)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"حروف تہجی (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"حروف تہجی (QWERTZ)"</string> diff --git a/java/res/values-uz-rUZ/strings.xml b/java/res/values-uz-rUZ/strings.xml index b696e3706..62143d7af 100644 --- a/java/res/values-uz-rUZ/strings.xml +++ b/java/res/values-uz-rUZ/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serb (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (an’anaviy)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Til aniqlanmadi (lotin)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Lotin (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Lotin (QWERTZ)"</string> diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml index 1f9590ef1..fa0e11b51 100644 --- a/java/res/values-vi/strings.xml +++ b/java/res/values-vi/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Tiếng Anh-Hindi (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Tiếng Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Truyền thống)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"Không ngôn ngữ nào (Bảng chữ cái)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Bảng chữ cái (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Bảng chữ cái (QWERTZ)"</string> diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml index 7524e324c..4562c4bd1 100644 --- a/java/res/values-zh-rCN/strings.xml +++ b/java/res/values-zh-rCN/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印地英语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"塞尔维亚语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>布局)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(传统)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"无语言(字母)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"字母 (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"字母 (QWERTZ)"</string> diff --git a/java/res/values-zh-rHK/strings.xml b/java/res/values-zh-rHK/strings.xml index 3c013ad4f..e584a88fe 100644 --- a/java/res/values-zh-rHK/strings.xml +++ b/java/res/values-zh-rHK/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印度英文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"塞爾維亞文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (傳統)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"無語言 (字母)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"字母 (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"字母 (QWERTZ)"</string> diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml index 28bbc8a46..aa534c869 100644 --- a/java/res/values-zh-rTW/strings.xml +++ b/java/res/values-zh-rTW/strings.xml @@ -102,6 +102,8 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印度英文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"塞爾維亞文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (傳統)"</string> + <!-- no translation found for subtype_generic_compact (3353673321203202922) --> + <skip /> <string name="subtype_no_language" msgid="7137390094240139495">"無語言 (字母)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"字母 (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"字母 (QWERTZ)"</string> diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml index 0c80aee61..0177129dc 100644 --- a/java/res/values-zu/strings.xml +++ b/java/res/values-zu/strings.xml @@ -102,6 +102,7 @@ <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"I-Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Isi-Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string> <string name="subtype_generic_traditional" msgid="8584594350973800586">"Isi-<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradition)"</string> + <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Okuqoqene ndawonye)"</string> <string name="subtype_no_language" msgid="7137390094240139495">"Alikho ulimi (Alfabhethi)"</string> <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabhethi (QWERTY)"</string> <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabhethi (QWERTZ)"</string> diff --git a/java/res/values/donottranslate-debug-settings.xml b/java/res/values/donottranslate-debug-settings.xml index c612010f6..491043f1a 100644 --- a/java/res/values/donottranslate-debug-settings.xml +++ b/java/res/values/donottranslate-debug-settings.xml @@ -43,6 +43,10 @@ <string name="prefs_key_popup_dismiss_end_y_scale_settings">Key popup dismiss end Y scale</string> <!-- Title of the settings for reading an external dictionary file --> <string name="prefs_read_external_dictionary">Read external dictionary file</string> + <!-- Title of the settings to enable keyboard resizing --> + <string name="prefs_resize_keyboard">Enable keyboard resizing</string> + <!-- Title of the settings for setting keyboard height --> + <string name="prefs_keyboard_height_scale">Keyboard height scale</string> <!-- Message to show when there are no files to install as an external dictionary [CHAR LIMIT=100] --> <string name="read_external_dictionary_no_files_message">No dictionary files in the Downloads folder</string> <!-- Title of the dialog that selects a file to install as an external dictionary [CHAR LIMIT=50] --> diff --git a/java/res/xml/prefs_screen_debug.xml b/java/res/xml/prefs_screen_debug.xml index 13edf3ec6..905bc045c 100644 --- a/java/res/xml/prefs_screen_debug.xml +++ b/java/res/xml/prefs_screen_debug.xml @@ -76,6 +76,17 @@ android:key="pref_key_preview_dismiss_duration" android:title="@string/prefs_key_popup_dismiss_duration_settings" latin:maxValue="100" /> <!-- milliseconds --> + <CheckBoxPreference + android:key="pref_resize_keyboard" + android:title="@string/prefs_resize_keyboard" + android:defaultValue="false" + android:persistent="true" /> + <com.android.inputmethod.latin.settings.SeekBarDialogPreference + android:dependency="pref_resize_keyboard" + android:key="pref_keyboard_height_scale" + android:title="@string/prefs_keyboard_height_scale" + latin:minValue="50" + latin:maxValue="120" /> <!-- percentage --> <PreferenceScreen android:key="read_external_dictionary" android:title="@string/prefs_read_external_dictionary" /> diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 3bcce4f69..89acc3cd3 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -110,7 +110,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mThemeContext, editorInfo); final Resources res = mThemeContext.getResources(); final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); - final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res); + final int keyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues); builder.setKeyboardGeometry(keyboardWidth, keyboardHeight); builder.setSubtype(mSubtypeSwitcher.getCurrentSubtype()); builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 6feb1e7ad..b07693c76 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -41,6 +41,8 @@ import com.android.inputmethod.latin.utils.TypefaceUtils; import java.util.HashSet; +import javax.annotation.Nullable; + /** * A view that renders a virtual {@link Keyboard}. * @@ -557,9 +559,10 @@ public class KeyboardView extends View { * @param key key in the attached {@link Keyboard}. * @see #invalidateAllKeys */ - public void invalidateKey(final Key key) { - if (mInvalidateAllKeys) return; - if (key == null) return; + public void invalidateKey(@Nullable final Key key) { + if (key == null || mInvalidateAllKeys) { + return; + } mInvalidatedKeys.add(key); final int x = key.getX() + getPaddingLeft(); final int y = key.getY() + getPaddingTop(); diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index f3aaaefbf..f23db04f3 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -39,7 +39,7 @@ import android.view.ViewGroup; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.MainKeyboardAccessibilityDelegate; import com.android.inputmethod.annotations.ExternallyReferenced; -import com.android.inputmethod.keyboard.internal.DrawingHandler; +import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.internal.DrawingPreviewPlacerView; import com.android.inputmethod.keyboard.internal.GestureFloatingTextDrawingPreview; import com.android.inputmethod.keyboard.internal.GestureTrailsDrawingPreview; @@ -64,6 +64,9 @@ import com.android.inputmethod.latin.utils.TypefaceUtils; import java.util.Locale; import java.util.WeakHashMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * A view that is responsible for detecting key presses and touch movements. * @@ -108,7 +111,7 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration */ public final class MainKeyboardView extends KeyboardView implements PointerTracker.DrawingProxy, - MoreKeysPanel.Controller, DrawingHandler.Callbacks, TimerHandler.Callbacks { + MoreKeysPanel.Controller { private static final String TAG = MainKeyboardView.class.getSimpleName(); /** Listener for {@link KeyboardActionListener}. */ @@ -164,11 +167,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private final KeyDetector mKeyDetector; private final NonDistinctMultitouchHelper mNonDistinctMultitouchHelper; - private final TimerHandler mKeyTimerHandler; + private final TimerHandler mTimerHandler; private final int mLanguageOnSpacebarHorizontalMargin; - private final DrawingHandler mDrawingHandler = new DrawingHandler(this); - private MainKeyboardAccessibilityDelegate mAccessibilityDelegate; public MainKeyboardView(final Context context, final AttributeSet attrs) { @@ -178,7 +179,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - mDrawingPreviewPlacerView = new DrawingPreviewPlacerView(context, attrs); + final DrawingPreviewPlacerView drawingPreviewPlacerView = + new DrawingPreviewPlacerView(context, attrs); final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); @@ -186,7 +188,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0); final int gestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0); - mKeyTimerHandler = new TimerHandler( + mTimerHandler = new TimerHandler( this, ignoreAltCodeKeyTimeout, gestureRecognitionUpdateTime); final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( @@ -196,7 +198,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mKeyDetector = new KeyDetector( keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); - PointerTracker.init(mainKeyboardViewAttr, mKeyTimerHandler, this /* DrawingProxy */); + PointerTracker.init(mainKeyboardViewAttr, mTimerHandler, this /* DrawingProxy */); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); final boolean forceNonDistinctMultitouch = prefs.getBoolean( @@ -246,15 +248,17 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mGestureFloatingTextDrawingPreview = new GestureFloatingTextDrawingPreview( mainKeyboardViewAttr); - mGestureFloatingTextDrawingPreview.setDrawingView(mDrawingPreviewPlacerView); + mGestureFloatingTextDrawingPreview.setDrawingView(drawingPreviewPlacerView); mGestureTrailsDrawingPreview = new GestureTrailsDrawingPreview(mainKeyboardViewAttr); - mGestureTrailsDrawingPreview.setDrawingView(mDrawingPreviewPlacerView); + mGestureTrailsDrawingPreview.setDrawingView(drawingPreviewPlacerView); mSlidingKeyInputDrawingPreview = new SlidingKeyInputDrawingPreview(mainKeyboardViewAttr); - mSlidingKeyInputDrawingPreview.setDrawingView(mDrawingPreviewPlacerView); + mSlidingKeyInputDrawingPreview.setDrawingView(drawingPreviewPlacerView); mainKeyboardViewAttr.recycle(); + mDrawingPreviewPlacerView = drawingPreviewPlacerView; + final LayoutInflater inflater = LayoutInflater.from(getContext()); mMoreKeysKeyboardContainer = inflater.inflate(moreKeysKeyboardLayoutId, null); mMoreKeysKeyboardForActionContainer = inflater.inflate( @@ -307,17 +311,24 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack animatorToStart.setCurrentPlayTime(startTime); } - // Implements {@link TimerHander.Callbacks} method. - @Override - public void startWhileTypingFadeinAnimation() { - cancelAndStartAnimators( - mAltCodeKeyWhileTypingFadeoutAnimator, mAltCodeKeyWhileTypingFadeinAnimator); - } - + // Implements {@link DrawingProxy#startWhileTypingAnimation(int)}. + /** + * Called when a while-typing-animation should be started. + * @param fadeInOrOut {@link DrawingProxy#FADE_IN} starts while-typing-fade-in animation. + * {@link DrawingProxy#FADE_OUT} starts while-typing-fade-out animation. + */ @Override - public void startWhileTypingFadeoutAnimation() { - cancelAndStartAnimators( - mAltCodeKeyWhileTypingFadeinAnimator, mAltCodeKeyWhileTypingFadeoutAnimator); + public void startWhileTypingAnimation(final int fadeInOrOut) { + switch (fadeInOrOut) { + case DrawingProxy.FADE_IN: + cancelAndStartAnimators( + mAltCodeKeyWhileTypingFadeoutAnimator, mAltCodeKeyWhileTypingFadeinAnimator); + break; + case DrawingProxy.FADE_OUT: + cancelAndStartAnimators( + mAltCodeKeyWhileTypingFadeinAnimator, mAltCodeKeyWhileTypingFadeoutAnimator); + break; + } } @ExternallyReferenced @@ -379,7 +390,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack @Override public void setKeyboard(final Keyboard keyboard) { // Remove any pending messages, except dismissing preview and key repeat. - mKeyTimerHandler.cancelLongPressTimers(); + mTimerHandler.cancelLongPressTimers(); super.setKeyboard(keyboard); mKeyDetector.setKeyboard( keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection()); @@ -451,17 +462,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack windowContentView.addView(mDrawingPreviewPlacerView); } - // Implements {@link DrawingHandler.Callbacks} method. @Override - public void dismissAllKeyPreviews() { - mKeyPreviewChoreographer.dismissAllKeyPreviews(); - PointerTracker.setReleasedKeyGraphicsToAllKeys(); - } - - @Override - public void showKeyPreview(final Key key) { + public void showKeyPreview(@Nonnull final Key key) { // If the key is invalid or has no key preview, we must not show key preview. - if (key == null || key.noKeyPreview()) { + if (key.noKeyPreview()) { return; } final Keyboard keyboard = getKeyboard(); @@ -480,22 +484,21 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated()); } - // Implements {@link TimerHandler.Callbacks} method. + // Implements {@link DrawingProxy#dismissKeyPreviewWithoutDelay(Key)}. @Override - public void dismissKeyPreviewWithoutDelay(final Key key) { + public void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) { mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */); - // To redraw key top letter. invalidateKey(key); } @Override - public void dismissKeyPreview(final Key key) { - if (!isHardwareAccelerated()) { - // TODO: Implement preference option to control key preview method and duration. - mDrawingHandler.dismissKeyPreview(mKeyPreviewDrawParams.getLingerTimeout(), key); + public void dismissKeyPreview(@Nonnull final Key key) { + if (isHardwareAccelerated()) { + mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */); return; } - mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */); + // TODO: Implement preference option to control key preview method and duration. + mTimerHandler.postDismissKeyPreview(key, mKeyPreviewDrawParams.getLingerTimeout()); } public void setSlidingKeyInputPreviewEnabled(final boolean enabled) { @@ -503,14 +506,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } @Override - public void showSlidingKeyInputPreview(final PointerTracker tracker) { + public void showSlidingKeyInputPreview(@Nullable final PointerTracker tracker) { locatePreviewPlacerView(); - mSlidingKeyInputDrawingPreview.setPreviewPosition(tracker); - } - - @Override - public void dismissSlidingKeyInputPreview() { - mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview(); + if (tracker != null) { + mSlidingKeyInputDrawingPreview.setPreviewPosition(tracker); + } else { + mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview(); + } } private void setGesturePreviewMode(final boolean isGestureTrailEnabled, @@ -519,20 +521,26 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mGestureTrailsDrawingPreview.setPreviewEnabled(isGestureTrailEnabled); } - // Implements {@link DrawingHandler.Callbacks} method. - @Override - public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) { + public void showGestureFloatingPreviewText(@Nonnull final SuggestedWords suggestedWords, + final boolean dismissDelayed) { locatePreviewPlacerView(); - mGestureFloatingTextDrawingPreview.setSuggetedWords(suggestedWords); + final GestureFloatingTextDrawingPreview gestureFloatingTextDrawingPreview = + mGestureFloatingTextDrawingPreview; + gestureFloatingTextDrawingPreview.setSuggetedWords(suggestedWords); + if (dismissDelayed) { + mTimerHandler.postDismissGestureFloatingPreviewText( + mGestureFloatingPreviewTextLingerTimeout); + } } - public void dismissGestureFloatingPreviewText() { - locatePreviewPlacerView(); - mDrawingHandler.dismissGestureFloatingPreviewText(mGestureFloatingPreviewTextLingerTimeout); + // Implements {@link DrawingProxy#dismissGestureFloatingPreviewTextWithoutDelay()}. + @Override + public void dismissGestureFloatingPreviewTextWithoutDelay() { + mGestureFloatingTextDrawingPreview.dismissGestureFloatingPreviewText(); } @Override - public void showGestureTrail(final PointerTracker tracker, + public void showGestureTrail(@Nonnull final PointerTracker tracker, final boolean showsFloatingPreviewText) { locatePreviewPlacerView(); if (showsFloatingPreviewText) { @@ -599,13 +607,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return moreKeysKeyboardView; } - // Implements {@link TimerHandler.Callbacks} method. + // Implements {@link DrawingProxy@onLongPress(PointerTracker)}. /** * Called when a key is long pressed. * @param tracker the pointer tracker which pressed the parent key */ @Override - public void onLongPress(final PointerTracker tracker) { + public void onLongPress(@Nonnull final PointerTracker tracker) { if (isShowingMoreKeysPanel()) { return; } @@ -660,7 +668,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener); tracker.onShowMoreKeysPanel(moreKeysPanel); // TODO: Implement zoom in animation of more keys panel. - dismissKeyPreviewWithoutDelay(key); + mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */); } public boolean isInDraggingFinger() { @@ -673,6 +681,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack @Override public void onShowMoreKeysPanel(final MoreKeysPanel panel) { locatePreviewPlacerView(); + // Dismiss another {@link MoreKeysPanel} that may be being showed. + onDismissMoreKeysPanel(); + // Dismiss all key previews that may be being showed. + PointerTracker.setReleasedKeyGraphicsToAllKeys(); + // Dismiss sliding key input preview that may be being showed. + mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview(); panel.showInParent(mDrawingPreviewPlacerView); mMoreKeysPanel = panel; } @@ -695,15 +709,15 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } public void startDoubleTapShiftKeyTimer() { - mKeyTimerHandler.startDoubleTapShiftKeyTimer(); + mTimerHandler.startDoubleTapShiftKeyTimer(); } public void cancelDoubleTapShiftKeyTimer() { - mKeyTimerHandler.cancelDoubleTapShiftKeyTimer(); + mTimerHandler.cancelDoubleTapShiftKeyTimer(); } public boolean isInDoubleTapShiftKeyTimeout() { - return mKeyTimerHandler.isInDoubleTapShiftKeyTimeout(); + return mTimerHandler.isInDoubleTapShiftKeyTimeout(); } @Override @@ -712,9 +726,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return false; } if (mNonDistinctMultitouchHelper != null) { - if (me.getPointerCount() > 1 && mKeyTimerHandler.isInKeyRepeat()) { + if (me.getPointerCount() > 1 && mTimerHandler.isInKeyRepeat()) { // Key repeating timer will be canceled if 2 or more keys are in action. - mKeyTimerHandler.cancelKeyRepeatTimers(); + mTimerHandler.cancelKeyRepeatTimers(); } // Non distinct multitouch screen support mNonDistinctMultitouchHelper.processMotionEvent(me, mKeyDetector); @@ -738,11 +752,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } public void cancelAllOngoingEvents() { - mKeyTimerHandler.cancelAllMessages(); - mDrawingHandler.cancelAllMessages(); - dismissAllKeyPreviews(); - dismissGestureFloatingPreviewText(); - dismissSlidingKeyInputPreview(); + mTimerHandler.cancelAllMessages(); + PointerTracker.setReleasedKeyGraphicsToAllKeys(); + mGestureFloatingTextDrawingPreview.dismissGestureFloatingPreviewText(); + mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview(); PointerTracker.dismissAllMoreKeysPanels(); PointerTracker.cancelAllPointerTrackers(); } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 5a540ff17..467f5150a 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -41,6 +41,9 @@ import com.android.inputmethod.latin.utils.ResourceUtils; import java.util.ArrayList; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public final class PointerTracker implements PointerTrackerQueue.Element, BatchInputArbiterListener { private static final String TAG = PointerTracker.class.getSimpleName(); @@ -50,12 +53,18 @@ public final class PointerTracker implements PointerTrackerQueue.Element, private static boolean DEBUG_MODE = DebugFlags.DEBUG_ENABLED || DEBUG_EVENT; public interface DrawingProxy { - public void invalidateKey(Key key); - public void showKeyPreview(Key key); - public void dismissKeyPreview(Key key); - public void showSlidingKeyInputPreview(PointerTracker tracker); - public void dismissSlidingKeyInputPreview(); - public void showGestureTrail(PointerTracker tracker, boolean showsFloatingPreviewText); + public void invalidateKey(@Nullable Key key); + public void showKeyPreview(@Nonnull Key key); + public void dismissKeyPreview(@Nonnull Key key); + public void dismissKeyPreviewWithoutDelay(@Nonnull Key key); + public void onLongPress(@Nonnull PointerTracker tracker); + public static final int FADE_IN = 0; + public static final int FADE_OUT = 1; + public void startWhileTypingAnimation(final int fadeInOrOut); + public void showSlidingKeyInputPreview(@Nullable PointerTracker tracker); + public void showGestureTrail(@Nonnull PointerTracker tracker, + boolean showsFloatingPreviewText); + public void dismissGestureFloatingPreviewTextWithoutDelay(); } public interface TimerProxy { @@ -163,6 +172,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, // The position and time at which first down event occurred. private long mDownTime; + @Nonnull private int[] mDownCoordinates = CoordinateUtils.newInstance(); private long mUpTime; @@ -416,6 +426,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return mIsInDraggingFinger; } + @Nullable public Key getKey() { return mCurrentKey; } @@ -429,12 +440,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return mKeyDetector.detectHitKey(x, y); } - private void setReleasedKeyGraphics(final Key key) { - sDrawingProxy.dismissKeyPreview(key); + private void setReleasedKeyGraphics(@Nullable final Key key) { if (key == null) { return; } + sDrawingProxy.dismissKeyPreview(key); // Even if the key is disabled, update the key release graphics just in case. updateReleaseKeyGraphics(key); @@ -518,7 +529,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return mGestureStrokeDrawingPoints; } - public void getLastCoordinates(final int[] outCoords) { + public void getLastCoordinates(@Nonnull final int[] outCoords) { CoordinateUtils.set(outCoords, mLastX, mLastY); } @@ -526,7 +537,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, return mDownTime; } - public void getDownCoordinates(final int[] outCoords) { + public void getDownCoordinates(@Nonnull final int[] outCoords) { CoordinateUtils.copy(outCoords, mDownCoordinates); } @@ -765,7 +776,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, private void resetKeySelectionByDraggingFinger() { mIsInDraggingFinger = false; mIsInSlidingKeyInput = false; - sDrawingProxy.dismissSlidingKeyInputPreview(); + sDrawingProxy.showSlidingKeyInputPreview(null /* tracker */); } private void onGestureMoveEvent(final int x, final int y, final long eventTime, diff --git a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java index 755a99a2c..c76a9aca4 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java @@ -22,6 +22,8 @@ import android.view.View; import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.keyboard.PointerTracker; +import javax.annotation.Nonnull; + /** * Abstract base class for previews that are drawn on DrawingPreviewPlacerView, e.g., * GestureFloatingTextDrawingPreview, GestureTrailsDrawingPreview, and @@ -32,7 +34,7 @@ public abstract class AbstractDrawingPreview { private boolean mPreviewEnabled; private boolean mHasValidGeometry; - public void setDrawingView(final DrawingPreviewPlacerView drawingView) { + public void setDrawingView(@Nonnull final DrawingPreviewPlacerView drawingView) { mDrawingView = drawingView; drawingView.addPreview(this); } @@ -61,7 +63,7 @@ public abstract class AbstractDrawingPreview { * @param width the width of {@link MainKeyboardView}. * @param height the height of {@link MainKeyboardView}. */ - public void setKeyboardViewGeometry(final int[] originCoords, final int width, + public void setKeyboardViewGeometry(@Nonnull final int[] originCoords, final int width, final int height) { mHasValidGeometry = (width > 0 && height > 0); } @@ -72,11 +74,11 @@ public abstract class AbstractDrawingPreview { * Draws the preview * @param canvas The canvas where the preview is drawn. */ - public abstract void drawPreview(final Canvas canvas); + public abstract void drawPreview(@Nonnull final Canvas canvas); /** * Set the position of the preview. * @param tracker The new location of the preview is based on the points in PointerTracker. */ - public abstract void setPreviewPosition(final PointerTracker tracker); + public abstract void setPreviewPosition(@Nonnull final PointerTracker tracker); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java deleted file mode 100644 index 1a55359f5..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java +++ /dev/null @@ -1,79 +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.keyboard.internal; - -import android.os.Message; - -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.internal.DrawingHandler.Callbacks; -import com.android.inputmethod.latin.SuggestedWords; -import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; - -import javax.annotation.Nonnull; - -// TODO: Separate this class into KeyPreviewHandler and BatchInputPreviewHandler or so. -public class DrawingHandler extends LeakGuardHandlerWrapper<Callbacks> { - public interface Callbacks { - public void dismissKeyPreviewWithoutDelay(Key key); - public void dismissAllKeyPreviews(); - public void showGestureFloatingPreviewText(SuggestedWords suggestedWords); - } - - private static final int MSG_DISMISS_KEY_PREVIEW = 0; - private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; - - public DrawingHandler(@Nonnull final Callbacks ownerInstance) { - super(ownerInstance); - } - - @Override - public void handleMessage(final Message msg) { - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { - return; - } - switch (msg.what) { - case MSG_DISMISS_KEY_PREVIEW: - callbacks.dismissKeyPreviewWithoutDelay((Key)msg.obj); - break; - case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: - callbacks.showGestureFloatingPreviewText(SuggestedWords.getEmptyInstance()); - break; - } - } - - public void dismissKeyPreview(final long delay, final Key key) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, key), delay); - } - - private void cancelAllDismissKeyPreviews() { - removeMessages(MSG_DISMISS_KEY_PREVIEW); - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { - return; - } - callbacks.dismissAllKeyPreviews(); - } - - public void dismissGestureFloatingPreviewText(final long delay) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay); - } - - public void cancelAllMessages() { - cancelAllDismissKeyPreviews(); - } -} diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java index 37ea0f17b..330ec52f0 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java @@ -29,6 +29,8 @@ import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.utils.CoordinateUtils; +import javax.annotation.Nonnull; + /** * The class for single gesture preview text. The class for multiple gesture preview text will be * derived from it. @@ -110,7 +112,11 @@ public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview { // Nothing to do here. } - public void setSuggetedWords(final SuggestedWords suggestedWords) { + public void dismissGestureFloatingPreviewText() { + setSuggetedWords(SuggestedWords.getEmptyInstance()); + } + + public void setSuggetedWords(@Nonnull final SuggestedWords suggestedWords) { if (!isPreviewEnabled()) { return; } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java index ddb193ead..d3764877c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java @@ -28,7 +28,6 @@ import com.android.inputmethod.latin.utils.ViewLayoutUtils; import java.util.ArrayDeque; import java.util.HashMap; -import java.util.HashSet; /** * This class controls pop up key previews. This class decides: @@ -69,12 +68,6 @@ public final class KeyPreviewChoreographer { return mShowingKeyPreviewViews.containsKey(key); } - public void dismissAllKeyPreviews() { - for (final Key key : new HashSet<>(mShowingKeyPreviewViews.keySet())) { - dismissKeyPreview(key, false /* withAnimation */); - } - } - public void dismissKeyPreview(final Key key, final boolean withAnimation) { if (key == null) { return; diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java index 076abbf4d..456522535 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java +++ b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java @@ -22,33 +22,29 @@ import android.view.ViewConfiguration; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.PointerTracker; +import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; -import com.android.inputmethod.keyboard.internal.TimerHandler.Callbacks; import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; import javax.annotation.Nonnull; -// TODO: Separate this class into KeyTimerHandler and BatchInputTimerHandler or so. -public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> implements TimerProxy { - public interface Callbacks { - public void startWhileTypingFadeinAnimation(); - public void startWhileTypingFadeoutAnimation(); - public void onLongPress(PointerTracker tracker); - } - +public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy> + implements TimerProxy { private static final int MSG_TYPING_STATE_EXPIRED = 0; private static final int MSG_REPEAT_KEY = 1; private static final int MSG_LONGPRESS_KEY = 2; private static final int MSG_LONGPRESS_SHIFT_KEY = 3; private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 4; private static final int MSG_UPDATE_BATCH_INPUT = 5; + private static final int MSG_DISMISS_KEY_PREVIEW = 6; + private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 7; private final int mIgnoreAltCodeKeyTimeout; private final int mGestureRecognitionUpdateTime; - public TimerHandler(@Nonnull final Callbacks ownerInstance, final int ignoreAltCodeKeyTimeout, - final int gestureRecognitionUpdateTime) { + public TimerHandler(@Nonnull final DrawingProxy ownerInstance, + final int ignoreAltCodeKeyTimeout, final int gestureRecognitionUpdateTime) { super(ownerInstance); mIgnoreAltCodeKeyTimeout = ignoreAltCodeKeyTimeout; mGestureRecognitionUpdateTime = gestureRecognitionUpdateTime; @@ -56,26 +52,35 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> imple @Override public void handleMessage(final Message msg) { - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { + final DrawingProxy drawingProxy = getOwnerInstance(); + if (drawingProxy == null) { return; } - final PointerTracker tracker = (PointerTracker) msg.obj; switch (msg.what) { case MSG_TYPING_STATE_EXPIRED: - callbacks.startWhileTypingFadeinAnimation(); + drawingProxy.startWhileTypingAnimation(DrawingProxy.FADE_IN); break; case MSG_REPEAT_KEY: - tracker.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */); + final PointerTracker tracker1 = (PointerTracker) msg.obj; + tracker1.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */); break; case MSG_LONGPRESS_KEY: case MSG_LONGPRESS_SHIFT_KEY: cancelLongPressTimers(); - callbacks.onLongPress(tracker); + final PointerTracker tracker2 = (PointerTracker) msg.obj; + drawingProxy.onLongPress(tracker2); break; case MSG_UPDATE_BATCH_INPUT: - tracker.updateBatchInputByTimer(SystemClock.uptimeMillis()); - startUpdateBatchInputTimer(tracker); + final PointerTracker tracker3 = (PointerTracker) msg.obj; + tracker3.updateBatchInputByTimer(SystemClock.uptimeMillis()); + startUpdateBatchInputTimer(tracker3); + break; + case MSG_DISMISS_KEY_PREVIEW: + final Key key = (Key) msg.obj; + drawingProxy.dismissKeyPreviewWithoutDelay(key); + break; + case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: + drawingProxy.dismissGestureFloatingPreviewTextWithoutDelay(); break; } } @@ -141,8 +146,8 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> imple final boolean isTyping = isTypingState(); removeMessages(MSG_TYPING_STATE_EXPIRED); - final Callbacks callbacks = getOwnerInstance(); - if (callbacks == null) { + final DrawingProxy drawingProxy = getOwnerInstance(); + if (drawingProxy == null) { return; } @@ -150,7 +155,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> imple final int typedCode = typedKey.getCode(); if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) { if (isTyping) { - callbacks.startWhileTypingFadeinAnimation(); + drawingProxy.startWhileTypingAnimation(DrawingProxy.FADE_IN); } return; } @@ -160,7 +165,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> imple if (isTyping) { return; } - callbacks.startWhileTypingFadeoutAnimation(); + drawingProxy.startWhileTypingAnimation(DrawingProxy.FADE_OUT); } @Override @@ -215,8 +220,18 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> imple removeMessages(MSG_UPDATE_BATCH_INPUT); } + public void postDismissKeyPreview(@Nonnull final Key key, final long delay) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, key), delay); + } + + public void postDismissGestureFloatingPreviewText(final long delay) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay); + } + public void cancelAllMessages() { cancelAllKeyTimers(); cancelAllUpdateBatchInputTimers(); + removeMessages(MSG_DISMISS_KEY_PREVIEW); + removeMessages(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 5fa28d571..3fa127005 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1501,14 +1501,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // This method must run on the UI Thread. - void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, + void showGesturePreviewAndSuggestionStrip(@Nonnull final SuggestedWords suggestedWords, final boolean dismissGestureFloatingPreviewText) { showSuggestionStrip(suggestedWords); final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); - mainKeyboardView.showGestureFloatingPreviewText(suggestedWords); - if (dismissGestureFloatingPreviewText) { - mainKeyboardView.dismissGestureFloatingPreviewText(); - } + mainKeyboardView.showGestureFloatingPreviewText(suggestedWords, + dismissGestureFloatingPreviewText /* dismissDelayed */); } // Called from PointerTracker through the KeyboardActionListener interface diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 89f2803cb..9b4619d35 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -160,24 +160,36 @@ public final class Suggest { || (consideredWord.length() > 1 && !didRemoveTypedWord); final boolean hasAutoCorrection; - // TODO: using isCorrectionEnabled here is not very good. It's probably useless, because - // any attempt to do auto-correction is already shielded with a test for this flag; at the - // 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 || resultsArePredictions - || suggestionResults.isEmpty() || wordComposer.hasDigits() - || wordComposer.isMostlyCaps() || wordComposer.isResumed() + // If correction is not enabled, we never auto-correct. This is for example for when + // the setting "Auto-correction" is "off": we still suggest, but we don't auto-correct. + if (!isCorrectionEnabled + // If the word does not allow to be auto-corrected, then we don't auto-correct. + || !allowsToBeAutoCorrected + // If we are doing prediction, then we never auto-correct of course + || resultsArePredictions + // If we don't have suggestion results, we can't evaluate the first suggestion + // for auto-correction + || suggestionResults.isEmpty() + // If the word has digits, we never auto-correct because it's likely the word + // was type with a lot of care + || wordComposer.hasDigits() + // If the word is mostly caps, we never auto-correct because this is almost + // certainly intentional (and careful input) + || wordComposer.isMostlyCaps() + // We never auto-correct when suggestions are resumed because it would be unexpected + || wordComposer.isResumed() + // If we don't have a main dictionary, we never want to auto-correct. The reason + // for this is, the user may have a contact whose name happens to match a valid + // word in their language, and it will unexpectedly auto-correct. For example, if + // the user types in English with no dictionary and has a "Will" in their contact + // list, "will" would always auto-correct to "Will" which is unwanted. Hence, no + // main dict => no auto-correct. Also, it would probably get obnoxious quickly. + // TODO: now that we have personalization, we may want to re-evaluate this decision || !mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary() + // If the first suggestion is a shortcut we never auto-correct to it, regardless + // of how strong it is (whitelist entries are not KIND_SHORTCUT but KIND_WHITELIST). + // TODO: we may want to have shortcut-only entries auto-correct in the future. || suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) { - // If we don't have a main dictionary, we never want to auto-correct. The reason for - // this is, the user may have a contact whose name happens to match a valid word in - // their language, and it will unexpectedly auto-correct. For example, if the user - // types in English with no dictionary and has a "Will" in their contact list, "will" - // would always auto-correct to "Will" which is unwanted. Hence, no main dict => no - // auto-correct. - // Also, shortcuts should never auto-correct unless they are whitelist entries. - // TODO: we may want to have shortcut-only entries auto-correct in the future. hasAutoCorrection = false; } else { final SuggestedWordInfo firstSuggestion = suggestionResults.first(); diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index b84de6919..c51e20f21 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -28,6 +28,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import javax.annotation.Nonnull; + public class SuggestedWords { public static final int INDEX_OF_TYPED_WORD = 0; public static final int INDEX_OF_AUTO_CORRECTION = 1; @@ -46,6 +48,7 @@ public class SuggestedWords { public static final int MAX_SUGGESTIONS = 18; private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST = new ArrayList<>(0); + @Nonnull private static final SuggestedWords EMPTY = new SuggestedWords( EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */, false /* isObsoleteSuggestions */, INPUT_STYLE_NONE); @@ -210,6 +213,7 @@ public class SuggestedWords { return result; } + @Nonnull public static final SuggestedWords getEmptyInstance() { return SuggestedWords.EMPTY; } diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 78d79ae50..5925bdc4e 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -171,14 +171,17 @@ public final class FormatSpec { // ExpandableDictionary.matchesExpectedBinaryDictFormatVersionForThisType(). public static final int VERSION2 = 2; public static final int VERSION201 = 201; + public static final int VERSION202 = 202; public static final int MINIMUM_SUPPORTED_VERSION_OF_CODE_POINT_TABLE = VERSION201; // Dictionary version used for testing. public static final int VERSION4_ONLY_FOR_TESTING = 399; public static final int VERSION401 = 401; public static final int VERSION4 = 402; public static final int VERSION4_DEV = 403; - static final int MINIMUM_SUPPORTED_VERSION = VERSION2; - static final int MAXIMUM_SUPPORTED_VERSION = VERSION4_DEV; + static final int MINIMUM_SUPPORTED_STATIC_VERSION = VERSION202; + static final int MAXIMUM_SUPPORTED_STATIC_VERSION = VERSION202; + static final int MINIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION4; + static final int MAXIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION4_DEV; // TODO: Make this value adaptative to content data, store it in the header, and // use it in the reading code. diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java index 4985c2f08..6fffb8e9d 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java @@ -29,6 +29,8 @@ public final class DebugSettings { public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch"; public static final String PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS = "pref_has_custom_key_preview_animation_params"; + public static final String PREF_RESIZE_KEYBOARD = "pref_resize_keyboard"; + public static final String PREF_KEYBOARD_HEIGHT_SCALE = "pref_keyboard_height_scale"; public static final String PREF_KEY_PREVIEW_DISMISS_DURATION = "pref_key_preview_dismiss_duration"; public static final String PREF_KEY_PREVIEW_DISMISS_END_X_SCALE = diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java index 2e5c3c479..068f56df1 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java @@ -89,6 +89,8 @@ public final class DebugSettingsFragment extends SubScreenFragment defaultKeyPreviewDismissEndScale); setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE, defaultKeyPreviewDismissEndScale); + setupKeyboardHeight( + DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE); mServiceNeedsRestart = false; mDebugMode = (TwoStatePreference) findPreference(DebugSettings.PREF_DEBUG_MODE); @@ -250,4 +252,51 @@ public final class DebugSettingsFragment extends SubScreenFragment public void feedbackValue(final int value) {} }); } + + private void setupKeyboardHeight(final String prefKey, final float defaultValue) { + final SharedPreferences prefs = getSharedPreferences(); + final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey); + if (pref == null) { + return; + } + pref.setInterface(new SeekBarDialogPreference.ValueProxy() { + private static final float PERCENTAGE_FLOAT = 100.0f; + private float getValueFromPercentage(final int percentage) { + return percentage / PERCENTAGE_FLOAT; + } + + private int getPercentageFromValue(final float floatValue) { + return (int)(floatValue * PERCENTAGE_FLOAT); + } + + @Override + public void writeValue(final int value, final String key) { + prefs.edit().putFloat(key, getValueFromPercentage(value)).apply(); + } + + @Override + public void writeDefaultValue(final String key) { + prefs.edit().remove(key).apply(); + } + + @Override + public int readValue(final String key) { + return getPercentageFromValue( + Settings.readKeyboardHeight(prefs, key, defaultValue)); + } + + @Override + public int readDefaultValue(final String key) { + return getPercentageFromValue(defaultValue); + } + + @Override + public String getValueText(final int value) { + return String.format(Locale.ROOT, "%d%%", value); + } + + @Override + public void feedbackValue(final int value) {} + }); + } } diff --git a/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java b/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java index 0fd94b0f8..5c416ab18 100644 --- a/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java +++ b/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java @@ -47,12 +47,14 @@ public class LocalSettingsConstants { DebugSettings.PREF_DEBUG_MODE, DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, + DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION, DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_X_SCALE, DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE, + DebugSettings.PREF_RESIZE_KEYBOARD, DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI, DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW }; diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java index 19db60655..16c053474 100644 --- a/java/src/com/android/inputmethod/latin/settings/Settings.java +++ b/java/src/com/android/inputmethod/latin/settings/Settings.java @@ -363,6 +363,12 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds : defaultValue; } + public static float readKeyboardHeight(final SharedPreferences prefs, + final String prefKey, final float defaultValue) { + final float percentage = prefs.getFloat(prefKey, UNDEFINED_PREFERENCE_VALUE_FLOAT); + return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue; + } + public static boolean readUseFullscreenMode(final Resources res) { return res.getBoolean(R.bool.config_use_fullscreen_mode); } diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index bdb4e64e0..509b41fd3 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -50,6 +50,7 @@ public class SettingsValues { private static final String FLOAT_MAX_VALUE_MARKER_STRING = "floatMaxValue"; private static final String FLOAT_NEGATIVE_INFINITY_MARKER_STRING = "floatNegativeInfinity"; private static final int TIMEOUT_TO_GET_TARGET_PACKAGE = 5; // seconds + public static final float DEFAULT_SIZE_SCALE = 1.0f; // 100% // From resources: public final SpacingAndPunctuations mSpacingAndPunctuations; @@ -110,6 +111,8 @@ public class SettingsValues { // Debug settings public final boolean mIsInternal; public final boolean mHasCustomKeyPreviewAnimationParams; + public final boolean mHasKeyboardResize; + public final float mKeyboardHeightScale; public final int mKeyPreviewShowUpDuration; public final int mKeyPreviewDismissDuration; public final float mKeyPreviewShowUpStartXScale; @@ -185,6 +188,9 @@ public class SettingsValues { mIsInternal = Settings.isInternal(prefs); mHasCustomKeyPreviewAnimationParams = prefs.getBoolean( DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, false); + mHasKeyboardResize = prefs.getBoolean(DebugSettings.PREF_RESIZE_KEYBOARD, false); + mKeyboardHeightScale = Settings.readKeyboardHeight( + prefs, DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, DEFAULT_SIZE_SCALE); mKeyPreviewShowUpDuration = Settings.readKeyPreviewAnimationDuration( prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION, res.getInteger(R.integer.config_key_preview_show_up_duration)); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index b18fcc744..b71bd1f50 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -344,12 +344,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick if (mSuggestedWords.size() <= mStartIndexOfMoreSuggestions) { return false; } - // Dismiss another {@link MoreKeysPanel} that may be being showed, for example - // {@link MoreKeysKeyboardView}. - mMainKeyboardView.onDismissMoreKeysPanel(); - // Dismiss all key previews and sliding key input preview that may be being showed. - mMainKeyboardView.dismissAllKeyPreviews(); - mMainKeyboardView.dismissSlidingKeyInputPreview(); final int stripWidth = getWidth(); final View container = mMoreSuggestionsContainer; final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight(); diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java index 727485724..1d7e7d683 100644 --- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java +++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java @@ -282,7 +282,6 @@ public class UserDictionarySettings extends ListFragment { } private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer { - private AlphabetIndexer mIndexer; private ViewBinder mViewBinder = new ViewBinder() { diff --git a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java index f9839eb91..01f5e1079 100644 --- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java @@ -22,16 +22,27 @@ import java.util.Collection; import javax.annotation.Nonnull; import javax.annotation.Nullable; +/** + * Utility methods for working with collections. + */ public final class CollectionUtils { private CollectionUtils() { // This utility class is not publicly instantiable. } + /** + * Converts a sub-range of the given array to an ArrayList of the appropriate type. + * @param array Array to be converted. + * @param start First index inclusive to be converted. + * @param end Last index exclusive to be converted. + * @throws IllegalArgumentException if start or end are out of range or start > end. + */ @Nonnull public static <E> ArrayList<E> arrayAsList(@Nonnull final E[] array, final int start, final int end) { if (start < 0 || start > end || end > array.length) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Invalid start: " + start + " end: " + end + + " with array.length: " + array.length); } final ArrayList<E> list = new ArrayList<>(end - start); diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java index 4e0f5f583..8699f2ce7 100644 --- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java @@ -36,7 +36,8 @@ public class CombinedFormatUtils { public static final String WORD_TAG = "word"; public static final String BEGINNING_OF_SENTENCE_TAG = "beginning_of_sentence"; public static final String NOT_A_WORD_TAG = "not_a_word"; - public static final String BLACKLISTED_TAG = "blacklisted"; + public static final String POSSIBLY_OFFENSIVE_TAG = "possibly_offensive"; + public static final String TRUE_VALUE = "true"; public static String formatAttributeMap(final HashMap<String, String> attributeMap) { final StringBuilder builder = new StringBuilder(); @@ -61,13 +62,13 @@ public class CombinedFormatUtils { builder.append(","); builder.append(formatProbabilityInfo(wordProperty.mProbabilityInfo)); if (wordProperty.mIsBeginningOfSentence) { - builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true"); + builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=" + TRUE_VALUE); } if (wordProperty.mIsNotAWord) { - builder.append("," + NOT_A_WORD_TAG + "=true"); + builder.append("," + NOT_A_WORD_TAG + "=" + TRUE_VALUE); } if (wordProperty.mIsPossiblyOffensive) { - builder.append("," + BLACKLISTED_TAG + "=true"); + builder.append("," + POSSIBLY_OFFENSIVE_TAG + "=" + TRUE_VALUE); } builder.append("\n"); if (wordProperty.mHasShortcuts) { @@ -111,4 +112,8 @@ public class CombinedFormatUtils { } return builder.toString(); } + + public static boolean isLiteralTrue(final String value) { + return TRUE_VALUE.equalsIgnoreCase(value); + } } diff --git a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java index d1fc642f3..cc0d470df 100644 --- a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java @@ -26,6 +26,7 @@ import android.util.TypedValue; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.settings.SettingsValues; import java.util.ArrayList; import java.util.HashMap; @@ -186,6 +187,15 @@ public final class ResourceUtils { return dm.widthPixels; } + public static int getKeyboardHeight(final Resources res, final SettingsValues settingsValues) { + final int defaultKeyboardHeight = getDefaultKeyboardHeight(res); + if (settingsValues.mHasKeyboardResize) { + // mKeyboardHeightScale Ranges from [.5,1.2], from xml/prefs_screen_debug.xml + return (int)(defaultKeyboardHeight * settingsValues.mKeyboardHeightScale); + } + return defaultKeyboardHeight; + } + public static int getDefaultKeyboardHeight(final Resources res) { final DisplayMetrics dm = res.getDisplayMetrics(); final String keyboardHeightInDp = getDeviceOverrideValue( diff --git a/native/jni/NativeFileList.mk b/native/jni/NativeFileList.mk index 7299ed3c0..55bb68344 100644 --- a/native/jni/NativeFileList.mk +++ b/native/jni/NativeFileList.mk @@ -71,7 +71,9 @@ LATIN_IME_CORE_SRC_FILES := \ ver4_patricia_trie_writing_helper.cpp \ ver4_pt_node_array_reader.cpp) \ $(addprefix suggest/policyimpl/dictionary/structure/v4/content/, \ + dynamic_language_model_probability_utils.cpp \ language_model_dict_content.cpp \ + language_model_dict_content_global_counters.cpp \ shortcut_dict_content.cpp \ sparse_table_dict_content.cpp \ terminal_position_lookup_table.cpp) \ @@ -83,6 +85,7 @@ LATIN_IME_CORE_SRC_FILES := \ forgetting_curve_utils.cpp \ format_utils.cpp \ mmapped_buffer.cpp \ + probability_utils.cpp \ sparse_table.cpp \ trie_map.cpp ) \ suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \ @@ -128,11 +131,13 @@ LATIN_IME_CORE_TEST_FILES := \ suggest/core/layout/normal_distribution_2d_test.cpp \ suggest/policyimpl/dictionary/header/header_read_write_utils_test.cpp \ suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp \ + suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp \ suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp \ suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp \ suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer_test.cpp \ suggest/policyimpl/dictionary/utils/byte_array_utils_test.cpp \ suggest/policyimpl/dictionary/utils/format_utils_test.cpp \ + suggest/policyimpl/dictionary/utils/probability_utils_test.cpp \ suggest/policyimpl/dictionary/utils/sparse_table_test.cpp \ suggest/policyimpl/dictionary/utils/trie_map_test.cpp \ suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy_test.cpp \ diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp index bfe17cc4c..6a5df9d95 100644 --- a/native/jni/src/suggest/core/dictionary/dictionary.cpp +++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp @@ -81,6 +81,9 @@ void Dictionary::NgramListenerForPrediction::onVisitEntry(const int ngramProbabi } const WordAttributes wordAttributes = mDictStructurePolicy->getWordAttributesInContext( mPrevWordIds, targetWordId, nullptr /* multiBigramMap */); + if (wordAttributes.getProbability() == NOT_A_PROBABILITY) { + return; + } mSuggestionResults->addPrediction(targetWordCodePoints, codePointCount, wordAttributes.getProbability()); } diff --git a/native/jni/src/suggest/core/dictionary/ngram_listener.h b/native/jni/src/suggest/core/dictionary/ngram_listener.h index e9b3c1aaf..2eb5e9fd1 100644 --- a/native/jni/src/suggest/core/dictionary/ngram_listener.h +++ b/native/jni/src/suggest/core/dictionary/ngram_listener.h @@ -26,6 +26,8 @@ namespace latinime { */ class NgramListener { public: + // ngramProbability is always 0 for v403 decaying dictionary. + // TODO: Remove ngramProbability. virtual void onVisitEntry(const int ngramProbability, const int targetWordId) = 0; virtual ~NgramListener() {}; diff --git a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp index 3283f6deb..23103b9f7 100644 --- a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp +++ b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp @@ -76,6 +76,52 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16; weightOfLangModelVsSpatialModelToOutputSuggestions, outSuggestionResults); } +/* static */ bool SuggestionsOutputUtils::shouldBlockWord( + const SuggestOptions *const suggestOptions, const DicNode *const terminalDicNode, + const WordAttributes wordAttributes, const bool isLastWord) { + const bool currentWordExactMatch = + ErrorTypeUtils::isExactMatch(terminalDicNode->getContainedErrorTypes()); + // When we have to block offensive words, non-exact matched offensive words should not be + // output. + const bool shouldBlockOffensiveWords = suggestOptions->blockOffensiveWords(); + + const bool isBlockedOffensiveWord = shouldBlockOffensiveWords && + wordAttributes.isPossiblyOffensive(); + + // This function is called in two situations: + // + // 1) At the end of a search, in which case terminalDicNode will point to the last DicNode + // of the search, and isLastWord will be true. + // "fuck" + // | + // \ terminalDicNode (isLastWord=true, currentWordExactMatch=true) + // In this case, if the current word is an exact match, we will always let the word + // through, even if the user is blocking offensive words (it's exactly what they typed!) + // + // 2) In the middle of the search, when we hit a terminal node, to decide whether or not + // to start a new search at root, to try to match the rest of the input. In this case, + // terminalDicNode will point to the terminal node we just hit, and isLastWord will be + // false. + // "fuckvthis" + // | + // \ terminalDicNode (isLastWord=false, currentWordExactMatch=true) + // + // In this case, we should NOT allow the match through (correcting "fuckthis" to "fuck this" + // when offensive words are blocked would be a bad idea). + // + // In the case of a multi-word correction where the offensive word is typed last (eg. + // for the input "allfuck"), this function will be called with isLastWord==true, but + // currentWordExactMatch==false. So we are OK in this case as well. + // "allfuck" + // | + // \ terminalDicNode (isLastWord=true, currentWordExactMatch=false) + if (isLastWord && currentWordExactMatch) { + return false; + } else { + return isBlockedOffensiveWord; + } +} + /* static */ void SuggestionsOutputUtils::outputSuggestionsOfDicNode( const Scoring *const scoringPolicy, DicTraverseSession *traverseSession, const DicNode *const terminalDicNode, const float weightOfLangModelVsSpatialModel, @@ -98,24 +144,16 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16; const bool isExactMatchWithIntentionalOmission = ErrorTypeUtils::isExactMatchWithIntentionalOmission( terminalDicNode->getContainedErrorTypes()); - const bool isFirstCharUppercase = terminalDicNode->isFirstCharUppercase(); - // Heuristic: We exclude probability=0 first-char-uppercase words from exact match. - // (e.g. "AMD" and "and") - const bool isSafeExactMatch = isExactMatch - && !(wordAttributes.isPossiblyOffensive() && isFirstCharUppercase); const int outputTypeFlags = (wordAttributes.isPossiblyOffensive() ? Dictionary::KIND_FLAG_POSSIBLY_OFFENSIVE : 0) - | ((isSafeExactMatch && boostExactMatches) ? Dictionary::KIND_FLAG_EXACT_MATCH : 0) + | ((isExactMatch && boostExactMatches) ? Dictionary::KIND_FLAG_EXACT_MATCH : 0) | (isExactMatchWithIntentionalOmission ? Dictionary::KIND_FLAG_EXACT_MATCH_WITH_INTENTIONAL_OMISSION : 0); - // Entries that are blacklisted or do not represent a word should not be output. const bool isValidWord = !(wordAttributes.isBlacklisted() || wordAttributes.isNotAWord()); - // When we have to block offensive words, non-exact matched offensive words should not be - // output. - const bool blockOffensiveWords = traverseSession->getSuggestOptions()->blockOffensiveWords(); - const bool isBlockedOffensiveWord = blockOffensiveWords && wordAttributes.isPossiblyOffensive() - && !isSafeExactMatch; + + const bool shouldBlockThisWord = shouldBlockWord(traverseSession->getSuggestOptions(), + terminalDicNode, wordAttributes, true /* isLastWord */); // Increase output score of top typing suggestion to ensure autocorrection. // TODO: Better integration with java side autocorrection logic. @@ -127,7 +165,7 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16; // Don't output invalid or blocked offensive words. However, we still need to submit their // shortcuts if any. - if (isValidWord && !isBlockedOffensiveWord) { + if (isValidWord && !shouldBlockThisWord) { int codePoints[MAX_WORD_LENGTH]; terminalDicNode->outputResult(codePoints); const int indexToPartialCommit = outputSecondWordFirstLetterInputIndex ? diff --git a/native/jni/src/suggest/core/result/suggestions_output_utils.h b/native/jni/src/suggest/core/result/suggestions_output_utils.h index bf8497828..eca1f78b2 100644 --- a/native/jni/src/suggest/core/result/suggestions_output_utils.h +++ b/native/jni/src/suggest/core/result/suggestions_output_utils.h @@ -18,6 +18,7 @@ #define LATINIME_SUGGESTIONS_OUTPUT_UTILS #include "defines.h" +#include "suggest/core/dictionary/word_attributes.h" namespace latinime { @@ -25,11 +26,19 @@ class BinaryDictionaryShortcutIterator; class DicNode; class DicTraverseSession; class Scoring; +class SuggestOptions; class SuggestionResults; class SuggestionsOutputUtils { public: /** + * Returns true if we should block the incoming word, in the context of the user's + * preferences to include or not include possibly offensive words + */ + static bool shouldBlockWord(const SuggestOptions *const suggestOptions, + const DicNode *const terminalDicNode, const WordAttributes wordAttributes, + const bool isLastWord); + /** * Outputs the final list of suggestions (i.e., terminal nodes). */ static void outputSuggestions(const Scoring *const scoringPolicy, diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp index 68a36454e..c372d668b 100644 --- a/native/jni/src/suggest/core/suggest.cpp +++ b/native/jni/src/suggest/core/suggest.cpp @@ -416,6 +416,11 @@ void Suggest::createNextWordDicNode(DicTraverseSession *traverseSession, DicNode traverseSession->getDictionaryStructurePolicy()->getWordAttributesInContext( dicNode->getPrevWordIds(), dicNode->getWordId(), traverseSession->getMultiBigramMap()); + if (SuggestionsOutputUtils::shouldBlockWord(traverseSession->getSuggestOptions(), + dicNode, wordAttributes, false /* isLastWord */)) { + return; + } + if (!TRAVERSAL->isGoodToTraverseNextWord(dicNode, wordAttributes.getProbability())) { return; } 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 44c2f443f..abc7f9906 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h @@ -134,9 +134,11 @@ class HeaderPolicy : public DictionaryHeaderStructurePolicy { // same so we use them for both here. switch (mDictFormatVersion) { case FormatUtils::VERSION_2: - return FormatUtils::VERSION_2; case FormatUtils::VERSION_201: - return FormatUtils::VERSION_201; + AKLOGE("Dictionary versions 2 and 201 are incompatible with this version"); + return FormatUtils::UNKNOWN_VERSION; + case FormatUtils::VERSION_202: + return FormatUtils::VERSION_202; case FormatUtils::VERSION_4_ONLY_FOR_TESTING: return FormatUtils::VERSION_4_ONLY_FOR_TESTING; case FormatUtils::VERSION_4: diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp index 41a8b13b8..d69a53fce 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp @@ -111,7 +111,8 @@ typedef DictionaryHeaderStructurePolicy::AttributeMap AttributeMap; switch (version) { case FormatUtils::VERSION_2: case FormatUtils::VERSION_201: - // Version 2 or 201 dictionary writing is not supported. + case FormatUtils::VERSION_202: + // None of the static dictionaries (v2x) support writing return false; case FormatUtils::VERSION_4_ONLY_FOR_TESTING: case FormatUtils::VERSION_4: diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp index 08e39ce43..9455222dd 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp @@ -140,7 +140,7 @@ const WordAttributes Ver4PatriciaTriePolicy::getWordAttributesInContext( const WordAttributes Ver4PatriciaTriePolicy::getWordAttributes(const int probability, const PtNodeParams &ptNodeParams) const { - return WordAttributes(probability, ptNodeParams.isBlacklisted(), ptNodeParams.isNotAWord(), + return WordAttributes(probability, false /* isBlacklisted */, ptNodeParams.isNotAWord(), ptNodeParams.getProbability() == 0); } @@ -164,7 +164,7 @@ int Ver4PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordI } const int ptNodePos = getTerminalPtNodePosFromWordId(wordId); const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos)); - if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) { + if (ptNodeParams.isDeleted() || ptNodeParams.isNotAWord()) { return NOT_A_PROBABILITY; } if (prevWordIds.empty()) { diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp index 372c9e36f..a19a384f4 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp @@ -115,7 +115,8 @@ template<class DictConstants, class DictBuffers, class DictBuffersPtr, class Str switch (formatVersion) { case FormatUtils::VERSION_2: case FormatUtils::VERSION_201: - AKLOGE("Given path is a directory but the format is version 2 or 201. path: %s", path); + case FormatUtils::VERSION_202: + AKLOGE("Given path is a directory but the format is version 2xx. path: %s", path); break; case FormatUtils::VERSION_4: { return newPolicyForV4Dict<backward::v402::Ver4DictConstants, @@ -177,6 +178,9 @@ template<class DictConstants, class DictBuffers, class DictBuffersPtr, class Str switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView())) { case FormatUtils::VERSION_2: case FormatUtils::VERSION_201: + AKLOGE("Dictionary versions 2 and 201 are incompatible with this version"); + break; + case FormatUtils::VERSION_202: return DictionaryStructureWithBufferPolicy::StructurePolicyPtr( new PatriciaTriePolicy(std::move(mmappedBuffer))); case FormatUtils::VERSION_4_ONLY_FOR_TESTING: diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h index 585e87a24..e52706e07 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h @@ -144,17 +144,6 @@ class PtNodeParams { return PatriciaTrieReadingUtils::isTerminal(mFlags); } - AK_FORCE_INLINE bool isBlacklisted() const { - // Note: this method will be removed in the next change. - // It is used in getProbabilityOfWord and getWordAttributes for both v402 and v403. - // * getProbabilityOfWord will be changed to no longer return NOT_A_PROBABILITY - // when isBlacklisted (i.e. to only check if isNotAWord or isDeleted) - // * getWordAttributes will be changed to always return blacklisted=false and - // isPossiblyOffensive according to the function below (instead of the current - // behaviour of checking if the probability is zero) - return PatriciaTrieReadingUtils::isPossiblyOffensive(mFlags); - } - AK_FORCE_INLINE bool isPossiblyOffensive() const { return PatriciaTrieReadingUtils::isPossiblyOffensive(mFlags); } diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp index 66fd18a52..59873612a 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ - #include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h" #include "defines.h" @@ -317,8 +316,8 @@ const WordAttributes PatriciaTriePolicy::getWordAttributesInContext( const WordAttributes PatriciaTriePolicy::getWordAttributes(const int probability, const PtNodeParams &ptNodeParams) const { - return WordAttributes(probability, ptNodeParams.isBlacklisted(), ptNodeParams.isNotAWord(), - ptNodeParams.getProbability() == 0); + return WordAttributes(probability, false /* isBlacklisted */, ptNodeParams.isNotAWord(), + ptNodeParams.isPossiblyOffensive()); } int PatriciaTriePolicy::getProbability(const int unigramProbability, @@ -345,10 +344,9 @@ int PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds, const int ptNodePos = getTerminalPtNodePosFromWordId(wordId); const PtNodeParams ptNodeParams = mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos); - if (ptNodeParams.isNotAWord() || ptNodeParams.isBlacklisted()) { - // If this is not a word, or if it's a blacklisted entry, it should behave as - // having no probability outside of the suggestion process (where it should be used - // for shortcuts). + if (ptNodeParams.isNotAWord()) { + // If this is not a word, it should behave as having no probability outside of the + // suggestion process (where it should be used for shortcuts). return NOT_A_PROBABILITY; } if (!prevWordIds.empty()) { diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.cpp new file mode 100644 index 000000000..b0fbb3e72 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.cpp @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#include "suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h" + +namespace latinime { + +// These counts are used to provide stable probabilities even if the user's input count is small. +const int DynamicLanguageModelProbabilityUtils::ASSUMED_MIN_COUNT_FOR_UNIGRAMS = 8192; +const int DynamicLanguageModelProbabilityUtils::ASSUMED_MIN_COUNT_FOR_BIGRAMS = 2; +const int DynamicLanguageModelProbabilityUtils::ASSUMED_MIN_COUNT_FOR_TRIGRAMS = 2; + +// These are encoded backoff weights. +// Note that we give positive value for trigrams that means the weight is more than 1. +// TODO: Apply backoff for main dictionaries and quit giving a positive backoff weight. +const int DynamicLanguageModelProbabilityUtils::ENCODED_BACKOFF_WEIGHT_FOR_UNIGRAMS = -32; +const int DynamicLanguageModelProbabilityUtils::ENCODED_BACKOFF_WEIGHT_FOR_BIGRAMS = 0; +const int DynamicLanguageModelProbabilityUtils::ENCODED_BACKOFF_WEIGHT_FOR_TRIGRAMS = 8; + +// This value is used to remove too old entries from the dictionary. +const int DynamicLanguageModelProbabilityUtils::DURATION_TO_DISCARD_ENTRY_IN_SECONDS = + 300 * 24 * 60 * 60; // 300 days + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h new file mode 100644 index 000000000..88bc58fe8 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h @@ -0,0 +1,114 @@ +/* + * 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. + */ + +#ifndef LATINIME_DYNAMIC_LANGUAGE_MODEL_PROBABILITY_UTILS_H +#define LATINIME_DYNAMIC_LANGUAGE_MODEL_PROBABILITY_UTILS_H + +#include <algorithm> + +#include "defines.h" +#include "suggest/core/dictionary/property/historical_info.h" +#include "utils/time_keeper.h" + +namespace latinime { + +class DynamicLanguageModelProbabilityUtils { + public: + static float computeRawProbabilityFromCounts(const int count, const int contextCount, + const int matchedWordCountInContext) { + int minCount = 0; + switch (matchedWordCountInContext) { + case 1: + minCount = ASSUMED_MIN_COUNT_FOR_UNIGRAMS; + break; + case 2: + minCount = ASSUMED_MIN_COUNT_FOR_BIGRAMS; + break; + case 3: + minCount = ASSUMED_MIN_COUNT_FOR_TRIGRAMS; + break; + default: + AKLOGE("computeRawProbabilityFromCounts is called with invalid " + "matchedWordCountInContext (%d).", matchedWordCountInContext); + ASSERT(false); + return 0.0f; + } + return static_cast<float>(count) / static_cast<float>(std::max(contextCount, minCount)); + } + + static float backoff(const int ngramProbability, const int matchedWordCountInContext) { + int probability = NOT_A_PROBABILITY; + + switch (matchedWordCountInContext) { + case 1: + probability = ngramProbability + ENCODED_BACKOFF_WEIGHT_FOR_UNIGRAMS; + break; + case 2: + probability = ngramProbability + ENCODED_BACKOFF_WEIGHT_FOR_BIGRAMS; + break; + case 3: + probability = ngramProbability + ENCODED_BACKOFF_WEIGHT_FOR_TRIGRAMS; + break; + default: + AKLOGE("backoff is called with invalid matchedWordCountInContext (%d).", + matchedWordCountInContext); + ASSERT(false); + return NOT_A_PROBABILITY; + } + return std::min(std::max(probability, NOT_A_PROBABILITY), MAX_PROBABILITY); + } + + static int getDecayedProbability(const int probability, const HistoricalInfo historicalInfo) { + const int elapsedTime = TimeKeeper::peekCurrentTime() - historicalInfo.getTimestamp(); + if (elapsedTime < 0) { + AKLOGE("The elapsed time is negatime value. Timestamp overflow?"); + return NOT_A_PROBABILITY; + } + // TODO: Improve this logic. + // We don't modify probability depending on the elapsed time. + return probability; + } + + static int shouldRemoveEntryDuringGC(const HistoricalInfo historicalInfo) { + // TODO: Improve this logic. + const int elapsedTime = TimeKeeper::peekCurrentTime() - historicalInfo.getTimestamp(); + return elapsedTime > DURATION_TO_DISCARD_ENTRY_IN_SECONDS; + } + + static int getPriorityToPreventFromEviction(const HistoricalInfo historicalInfo) { + // TODO: Improve this logic. + // More recently input entries get higher priority. + return historicalInfo.getTimestamp(); + } + +private: + DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicLanguageModelProbabilityUtils); + + static_assert(MAX_PREV_WORD_COUNT_FOR_N_GRAM <= 2, "Max supported Ngram is Trigram."); + + static const int ASSUMED_MIN_COUNT_FOR_UNIGRAMS; + static const int ASSUMED_MIN_COUNT_FOR_BIGRAMS; + static const int ASSUMED_MIN_COUNT_FOR_TRIGRAMS; + + static const int ENCODED_BACKOFF_WEIGHT_FOR_UNIGRAMS; + static const int ENCODED_BACKOFF_WEIGHT_FOR_BIGRAMS; + static const int ENCODED_BACKOFF_WEIGHT_FOR_TRIGRAMS; + + static const int DURATION_TO_DISCARD_ENTRY_IN_SECONDS; +}; + +} // namespace latinime +#endif /* LATINIME_DYNAMIC_LANGUAGE_MODEL_PROBABILITY_UTILS_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp index 509bd683b..31b1ea696 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp @@ -19,14 +19,16 @@ #include <algorithm> #include <cstring> -#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h" +#include "suggest/policyimpl/dictionary/utils/probability_utils.h" namespace latinime { -const int LanguageModelDictContent::DUMMY_PROBABILITY_FOR_VALID_WORDS = 1; +const int LanguageModelDictContent::TRIE_MAP_BUFFER_INDEX = 0; +const int LanguageModelDictContent::GLOBAL_COUNTERS_BUFFER_INDEX = 1; bool LanguageModelDictContent::save(FILE *const file) const { - return mTrieMap.save(file); + return mTrieMap.save(file) && mGlobalCounters.save(file); } bool LanguageModelDictContent::runGC( @@ -37,7 +39,8 @@ bool LanguageModelDictContent::runGC( } const WordAttributes LanguageModelDictContent::getWordAttributes(const WordIdArrayView prevWordIds, - const int wordId, const HeaderPolicy *const headerPolicy) const { + const int wordId, const bool mustMatchAllPrevWords, + const HeaderPolicy *const headerPolicy) const { int bitmapEntryIndices[MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1]; bitmapEntryIndices[0] = mTrieMap.getRootBitmapEntryIndex(); int maxPrevWordCount = 0; @@ -51,7 +54,15 @@ const WordAttributes LanguageModelDictContent::getWordAttributes(const WordIdArr bitmapEntryIndices[i + 1] = nextBitmapEntryIndex; } + const ProbabilityEntry unigramProbabilityEntry = getProbabilityEntry(wordId); + if (mHasHistoricalInfo && unigramProbabilityEntry.getHistoricalInfo()->getCount() == 0) { + // The word should be treated as a invalid word. + return WordAttributes(); + } for (int i = maxPrevWordCount; i >= 0; --i) { + if (mustMatchAllPrevWords && prevWordIds.size() > static_cast<size_t>(i)) { + break; + } const TrieMap::Result result = mTrieMap.get(wordId, bitmapEntryIndices[i]); if (!result.mIsValid) { continue; @@ -60,36 +71,39 @@ const WordAttributes LanguageModelDictContent::getWordAttributes(const WordIdArr ProbabilityEntry::decode(result.mValue, mHasHistoricalInfo); int probability = NOT_A_PROBABILITY; if (mHasHistoricalInfo) { - const int rawProbability = ForgettingCurveUtils::decodeProbability( - probabilityEntry.getHistoricalInfo(), headerPolicy); - if (rawProbability == NOT_A_PROBABILITY) { - // The entry should not be treated as a valid entry. - continue; - } + const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo(); + int contextCount = 0; if (i == 0) { // unigram - probability = rawProbability; + contextCount = mGlobalCounters.getTotalCount(); } else { const ProbabilityEntry prevWordProbabilityEntry = getNgramProbabilityEntry( prevWordIds.skip(1 /* n */).limit(i - 1), prevWordIds[0]); if (!prevWordProbabilityEntry.isValid()) { continue; } - if (prevWordProbabilityEntry.representsBeginningOfSentence()) { - probability = rawProbability; - } else { - const int prevWordRawProbability = ForgettingCurveUtils::decodeProbability( - prevWordProbabilityEntry.getHistoricalInfo(), headerPolicy); - probability = std::min(MAX_PROBABILITY - prevWordRawProbability - + rawProbability, MAX_PROBABILITY); + if (prevWordProbabilityEntry.representsBeginningOfSentence() + && historicalInfo->getCount() == 1) { + // BoS ngram requires multiple contextCount. + continue; } + contextCount = prevWordProbabilityEntry.getHistoricalInfo()->getCount(); } + const float rawProbability = + DynamicLanguageModelProbabilityUtils::computeRawProbabilityFromCounts( + historicalInfo->getCount(), contextCount, i + 1); + const int encodedRawProbability = + ProbabilityUtils::encodeRawProbability(rawProbability); + const int decayedProbability = + DynamicLanguageModelProbabilityUtils::getDecayedProbability( + encodedRawProbability, *historicalInfo); + probability = DynamicLanguageModelProbabilityUtils::backoff( + decayedProbability, i + 1 /* n */); } else { probability = probabilityEntry.getProbability(); } // TODO: Some flags in unigramProbabilityEntry should be overwritten by flags in // probabilityEntry. - const ProbabilityEntry unigramProbabilityEntry = getProbabilityEntry(wordId); return WordAttributes(probability, unigramProbabilityEntry.isBlacklisted(), unigramProbabilityEntry.isNotAWord(), unigramProbabilityEntry.isPossiblyOffensive()); @@ -165,7 +179,8 @@ void LanguageModelDictContent::exportAllNgramEntriesRelatedToWordInner( ProbabilityEntry::decode(entry.value(), mHasHistoricalInfo); if (probabilityEntry.isValid()) { const WordAttributes wordAttributes = getWordAttributes( - WordIdArrayView(*prevWordIds), wordId, headerPolicy); + WordIdArrayView(*prevWordIds), wordId, true /* mustMatchAllPrevWords */, + headerPolicy); outBummpedFullEntryInfo->emplace_back(*prevWordIds, wordId, wordAttributes, probabilityEntry); } @@ -212,6 +227,9 @@ bool LanguageModelDictContent::updateAllEntriesOnInputWord(const WordIdArrayView if (!setProbabilityEntry(wordId, &updatedUnigramProbabilityEntry)) { return false; } + mGlobalCounters.incrementTotalCount(); + mGlobalCounters.updateMaxValueOfCounters( + updatedUnigramProbabilityEntry.getHistoricalInfo()->getCount()); for (size_t i = 0; i < prevWordIds.size(); ++i) { if (prevWordIds[i] == NOT_A_WORD_ID) { break; @@ -225,6 +243,8 @@ bool LanguageModelDictContent::updateAllEntriesOnInputWord(const WordIdArrayView if (!setNgramProbabilityEntry(limitedPrevWordIds, wordId, &updatedNgramProbabilityEntry)) { return false; } + mGlobalCounters.updateMaxValueOfCounters( + updatedNgramProbabilityEntry.getHistoricalInfo()->getCount()); if (!originalNgramProbabilityEntry.isValid()) { entryCountersToUpdate->incrementNgramCount(i + 2); } @@ -235,10 +255,9 @@ bool LanguageModelDictContent::updateAllEntriesOnInputWord(const WordIdArrayView const ProbabilityEntry LanguageModelDictContent::createUpdatedEntryFrom( const ProbabilityEntry &originalProbabilityEntry, const bool isValid, const HistoricalInfo historicalInfo, const HeaderPolicy *const headerPolicy) const { - const HistoricalInfo updatedHistoricalInfo = ForgettingCurveUtils::createUpdatedHistoricalInfo( - originalProbabilityEntry.getHistoricalInfo(), isValid ? - DUMMY_PROBABILITY_FOR_VALID_WORDS : NOT_A_PROBABILITY, - &historicalInfo, headerPolicy); + const HistoricalInfo updatedHistoricalInfo = HistoricalInfo(historicalInfo.getTimestamp(), + 0 /* level */, originalProbabilityEntry.getHistoricalInfo()->getCount() + + historicalInfo.getCount()); if (originalProbabilityEntry.isValid()) { return ProbabilityEntry(originalProbabilityEntry.getFlags(), &updatedHistoricalInfo); } else { @@ -304,7 +323,7 @@ int LanguageModelDictContent::getBitmapEntryIndex(const WordIdArrayView prevWord bool LanguageModelDictContent::updateAllProbabilityEntriesForGCInner(const int bitmapEntryIndex, const int prevWordCount, const HeaderPolicy *const headerPolicy, - MutableEntryCounters *const outEntryCounters) { + const bool needsToHalveCounters, MutableEntryCounters *const outEntryCounters) { for (const auto &entry : mTrieMap.getEntriesInSpecifiedLevel(bitmapEntryIndex)) { if (prevWordCount > MAX_PREV_WORD_COUNT_FOR_N_GRAM) { AKLOGE("Invalid prevWordCount. prevWordCount: %d, MAX_PREV_WORD_COUNT_FOR_N_GRAM: %d.", @@ -321,33 +340,41 @@ bool LanguageModelDictContent::updateAllProbabilityEntriesForGCInner(const int b } continue; } - if (mHasHistoricalInfo && !probabilityEntry.representsBeginningOfSentence() - && probabilityEntry.isValid()) { - const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave( - probabilityEntry.getHistoricalInfo(), headerPolicy); - if (ForgettingCurveUtils::needsToKeep(&historicalInfo, headerPolicy)) { - // Update the entry. - const ProbabilityEntry updatedEntry(probabilityEntry.getFlags(), &historicalInfo); - if (!mTrieMap.put(entry.key(), updatedEntry.encode(mHasHistoricalInfo), - bitmapEntryIndex)) { - return false; - } - } else { + if (mHasHistoricalInfo && probabilityEntry.isValid()) { + const HistoricalInfo *originalHistoricalInfo = probabilityEntry.getHistoricalInfo(); + if (DynamicLanguageModelProbabilityUtils::shouldRemoveEntryDuringGC( + *originalHistoricalInfo)) { // Remove the entry. if (!mTrieMap.remove(entry.key(), bitmapEntryIndex)) { return false; } continue; } + if (needsToHalveCounters) { + const int updatedCount = originalHistoricalInfo->getCount() / 2; + if (updatedCount == 0) { + // Remove the entry. + if (!mTrieMap.remove(entry.key(), bitmapEntryIndex)) { + return false; + } + continue; + } + const HistoricalInfo historicalInfoToSave(originalHistoricalInfo->getTimestamp(), + originalHistoricalInfo->getLevel(), updatedCount); + const ProbabilityEntry updatedEntry(probabilityEntry.getFlags(), + &historicalInfoToSave); + if (!mTrieMap.put(entry.key(), updatedEntry.encode(mHasHistoricalInfo), + bitmapEntryIndex)) { + return false; + } + } } - if (!probabilityEntry.representsBeginningOfSentence()) { - outEntryCounters->incrementNgramCount(prevWordCount + 1); - } + outEntryCounters->incrementNgramCount(prevWordCount + 1); if (!entry.hasNextLevelMap()) { continue; } if (!updateAllProbabilityEntriesForGCInner(entry.getNextLevelBitmapEntryIndex(), - prevWordCount + 1, headerPolicy, outEntryCounters)) { + prevWordCount + 1, headerPolicy, needsToHalveCounters, outEntryCounters)) { return false; } } @@ -401,11 +428,11 @@ bool LanguageModelDictContent::getEntryInfo(const HeaderPolicy *const headerPoli } const ProbabilityEntry probabilityEntry = ProbabilityEntry::decode(entry.value(), mHasHistoricalInfo); - const int probability = (mHasHistoricalInfo) ? - ForgettingCurveUtils::decodeProbability(probabilityEntry.getHistoricalInfo(), - headerPolicy) : probabilityEntry.getProbability(); - outEntryInfo->emplace_back(probability, - probabilityEntry.getHistoricalInfo()->getTimestamp(), + const int priority = mHasHistoricalInfo + ? DynamicLanguageModelProbabilityUtils::getPriorityToPreventFromEviction( + *probabilityEntry.getHistoricalInfo()) + : probabilityEntry.getProbability(); + outEntryInfo->emplace_back(priority, probabilityEntry.getHistoricalInfo()->getCount(), entry.key(), targetLevel, prevWordIds->data()); } return true; @@ -413,11 +440,11 @@ bool LanguageModelDictContent::getEntryInfo(const HeaderPolicy *const headerPoli bool LanguageModelDictContent::EntryInfoToTurncate::Comparator::operator()( const EntryInfoToTurncate &left, const EntryInfoToTurncate &right) const { - if (left.mProbability != right.mProbability) { - return left.mProbability < right.mProbability; + if (left.mPriority != right.mPriority) { + return left.mPriority < right.mPriority; } - if (left.mTimestamp != right.mTimestamp) { - return left.mTimestamp > right.mTimestamp; + if (left.mCount != right.mCount) { + return left.mCount < right.mCount; } if (left.mKey != right.mKey) { return left.mKey < right.mKey; @@ -434,10 +461,9 @@ bool LanguageModelDictContent::EntryInfoToTurncate::Comparator::operator()( return false; } -LanguageModelDictContent::EntryInfoToTurncate::EntryInfoToTurncate(const int probability, - const int timestamp, const int key, const int prevWordCount, const int *const prevWordIds) - : mProbability(probability), mTimestamp(timestamp), mKey(key), - mPrevWordCount(prevWordCount) { +LanguageModelDictContent::EntryInfoToTurncate::EntryInfoToTurncate(const int priority, + const int count, const int key, const int prevWordCount, const int *const prevWordIds) + : mPriority(priority), mCount(count), mKey(key), mPrevWordCount(prevWordCount) { memmove(mPrevWordIds, prevWordIds, mPrevWordCount * sizeof(mPrevWordIds[0])); } diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h index 1cccf92d2..9678c35f9 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h @@ -22,6 +22,7 @@ #include "defines.h" #include "suggest/core/dictionary/word_attributes.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.h" #include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h" #include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h" #include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" @@ -131,15 +132,17 @@ class LanguageModelDictContent { const ProbabilityEntry mProbabilityEntry; }; - LanguageModelDictContent(const ReadWriteByteArrayView trieMapBuffer, + LanguageModelDictContent(const ReadWriteByteArrayView *const buffers, const bool hasHistoricalInfo) - : mTrieMap(trieMapBuffer), mHasHistoricalInfo(hasHistoricalInfo) {} + : mTrieMap(buffers[TRIE_MAP_BUFFER_INDEX]), + mGlobalCounters(buffers[GLOBAL_COUNTERS_BUFFER_INDEX]), + mHasHistoricalInfo(hasHistoricalInfo) {} explicit LanguageModelDictContent(const bool hasHistoricalInfo) - : mTrieMap(), mHasHistoricalInfo(hasHistoricalInfo) {} + : mTrieMap(), mGlobalCounters(), mHasHistoricalInfo(hasHistoricalInfo) {} bool isNearSizeLimit() const { - return mTrieMap.isNearSizeLimit(); + return mTrieMap.isNearSizeLimit() || mGlobalCounters.needsToHalveCounters(); } bool save(FILE *const file) const; @@ -148,13 +151,14 @@ class LanguageModelDictContent { const LanguageModelDictContent *const originalContent); const WordAttributes getWordAttributes(const WordIdArrayView prevWordIds, const int wordId, - const HeaderPolicy *const headerPolicy) const; + const bool mustMatchAllPrevWords, const HeaderPolicy *const headerPolicy) const; ProbabilityEntry getProbabilityEntry(const int wordId) const { return getNgramProbabilityEntry(WordIdArrayView(), wordId); } bool setProbabilityEntry(const int wordId, const ProbabilityEntry *const probabilityEntry) { + mGlobalCounters.addToTotalCount(probabilityEntry->getHistoricalInfo()->getCount()); return setNgramProbabilityEntry(WordIdArrayView(), wordId, probabilityEntry); } @@ -177,8 +181,15 @@ class LanguageModelDictContent { bool updateAllProbabilityEntriesForGC(const HeaderPolicy *const headerPolicy, MutableEntryCounters *const outEntryCounters) { - return updateAllProbabilityEntriesForGCInner(mTrieMap.getRootBitmapEntryIndex(), - 0 /* prevWordCount */, headerPolicy, outEntryCounters); + if (!updateAllProbabilityEntriesForGCInner(mTrieMap.getRootBitmapEntryIndex(), + 0 /* prevWordCount */, headerPolicy, mGlobalCounters.needsToHalveCounters(), + outEntryCounters)) { + return false; + } + if (mGlobalCounters.needsToHalveCounters()) { + mGlobalCounters.halveCounters(); + } + return true; } // entryCounts should be created by updateAllProbabilityEntries. @@ -203,11 +214,12 @@ class LanguageModelDictContent { DISALLOW_ASSIGNMENT_OPERATOR(Comparator); }; - EntryInfoToTurncate(const int probability, const int timestamp, const int key, + EntryInfoToTurncate(const int priority, const int count, const int key, const int prevWordCount, const int *const prevWordIds); - int mProbability; - int mTimestamp; + int mPriority; + // TODO: Remove. + int mCount; int mKey; int mPrevWordCount; int mPrevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1]; @@ -216,10 +228,11 @@ class LanguageModelDictContent { DISALLOW_DEFAULT_CONSTRUCTOR(EntryInfoToTurncate); }; - // TODO: Remove - static const int DUMMY_PROBABILITY_FOR_VALID_WORDS; + static const int TRIE_MAP_BUFFER_INDEX; + static const int GLOBAL_COUNTERS_BUFFER_INDEX; TrieMap mTrieMap; + LanguageModelDictContentGlobalCounters mGlobalCounters; const bool mHasHistoricalInfo; bool runGCInner(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap, @@ -227,7 +240,8 @@ class LanguageModelDictContent { int createAndGetBitmapEntryIndex(const WordIdArrayView prevWordIds); int getBitmapEntryIndex(const WordIdArrayView prevWordIds) const; bool updateAllProbabilityEntriesForGCInner(const int bitmapEntryIndex, const int prevWordCount, - const HeaderPolicy *const headerPolicy, MutableEntryCounters *const outEntryCounters); + const HeaderPolicy *const headerPolicy, const bool needsToHalveCounters, + MutableEntryCounters *const outEntryCounters); bool turncateEntriesInSpecifiedLevel(const HeaderPolicy *const headerPolicy, const int maxEntryCount, const int targetLevel, int *const outEntryCount); bool getEntryInfo(const HeaderPolicy *const headerPolicy, const int targetLevel, diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.cpp new file mode 100644 index 000000000..d6d91887e --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.cpp @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.h" + +#include <climits> + +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" + +namespace latinime { + +const int LanguageModelDictContentGlobalCounters::COUNTER_VALUE_NEAR_LIMIT_THRESHOLD = + (1 << (Ver4DictConstants::WORD_COUNT_FIELD_SIZE * CHAR_BIT)) - 64; +const int LanguageModelDictContentGlobalCounters::TOTAL_COUNT_VALUE_NEAR_LIMIT_THRESHOLD = 1 << 30; +const int LanguageModelDictContentGlobalCounters::COUNTER_SIZE_IN_BYTES = 4; +const int LanguageModelDictContentGlobalCounters::TOTAL_COUNT_INDEX = 0; +const int LanguageModelDictContentGlobalCounters::MAX_VALUE_OF_COUNTERS_INDEX = 1; + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.h new file mode 100644 index 000000000..283c2691a --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.h @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#ifndef LATINIME_LANGUAGE_MODEL_DICT_CONTENT_GLOBAL_COUNTERS_H +#define LATINIME_LANGUAGE_MODEL_DICT_CONTENT_GLOBAL_COUNTERS_H + +#include <cstdio> + +#include "defines.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" +#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h" +#include "utils/byte_array_view.h" + +namespace latinime { + +class LanguageModelDictContentGlobalCounters { + public: + explicit LanguageModelDictContentGlobalCounters(const ReadWriteByteArrayView buffer) + : mBuffer(buffer, 0 /* maxAdditionalBufferSize */), + mTotalCount(readValue(mBuffer, TOTAL_COUNT_INDEX)), + mMaxValueOfCounters(readValue(mBuffer, MAX_VALUE_OF_COUNTERS_INDEX)) {} + + LanguageModelDictContentGlobalCounters() + : mBuffer(0 /* maxAdditionalBufferSize */), mTotalCount(0), mMaxValueOfCounters(0) {} + + bool needsToHalveCounters() const { + return mMaxValueOfCounters >= COUNTER_VALUE_NEAR_LIMIT_THRESHOLD + || mTotalCount >= TOTAL_COUNT_VALUE_NEAR_LIMIT_THRESHOLD; + } + + int getTotalCount() const { + return mTotalCount; + } + + bool save(FILE *const file) const { + BufferWithExtendableBuffer bufferToWrite( + BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE); + if (!bufferToWrite.writeUint(mTotalCount, COUNTER_SIZE_IN_BYTES, + TOTAL_COUNT_INDEX * COUNTER_SIZE_IN_BYTES)) { + return false; + } + if (!bufferToWrite.writeUint(mMaxValueOfCounters, COUNTER_SIZE_IN_BYTES, + MAX_VALUE_OF_COUNTERS_INDEX * COUNTER_SIZE_IN_BYTES)) { + return false; + } + return DictFileWritingUtils::writeBufferToFileTail(file, &bufferToWrite); + } + + void incrementTotalCount() { + mTotalCount += 1; + } + + void addToTotalCount(const int count) { + mTotalCount += count; + } + + void updateMaxValueOfCounters(const int count) { + mMaxValueOfCounters = std::max(count, mMaxValueOfCounters); + } + + void halveCounters() { + mMaxValueOfCounters /= 2; + mTotalCount /= 2; + } + +private: + DISALLOW_COPY_AND_ASSIGN(LanguageModelDictContentGlobalCounters); + + const static int COUNTER_VALUE_NEAR_LIMIT_THRESHOLD; + const static int TOTAL_COUNT_VALUE_NEAR_LIMIT_THRESHOLD; + const static int COUNTER_SIZE_IN_BYTES; + const static int TOTAL_COUNT_INDEX; + const static int MAX_VALUE_OF_COUNTERS_INDEX; + + BufferWithExtendableBuffer mBuffer; + int mTotalCount; + int mMaxValueOfCounters; + + static int readValue(const BufferWithExtendableBuffer &buffer, const int index) { + const int pos = COUNTER_SIZE_IN_BYTES * index; + if (pos + COUNTER_SIZE_IN_BYTES > buffer.getTailPosition()) { + return 0; + } + return buffer.readUint(COUNTER_SIZE_IN_BYTES, pos); + } +}; +} // namespace latinime +#endif /* LATINIME_LANGUAGE_MODEL_DICT_CONTENT_GLOBAL_COUNTERS_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp index 45f88e9b2..4d088dcab 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp @@ -179,7 +179,7 @@ Ver4DictBuffers::Ver4DictBuffers(MmappedBuffer::MmappedBufferPtr &&headerBuffer, BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), mTerminalPositionLookupTable( contentBuffers[Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX]), - mLanguageModelDictContent(contentBuffers[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX], + mLanguageModelDictContent(&contentBuffers[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX], mHeaderPolicy.hasHistoricalInfoOfWords()), mShortcutDictContent(&contentBuffers[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX]), mIsUpdatable(mDictBuffer->isUpdatable()) {} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp index 8e6cb974b..eb6080a24 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp @@ -67,6 +67,6 @@ const int Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK = 0x80; const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT = 1; const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT = 3; -const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT = 1; +const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT = 2; } // namespace latinime 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 d3de322f9..96d789f58 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 @@ -110,7 +110,7 @@ const WordAttributes Ver4PatriciaTriePolicy::getWordAttributesInContext( return WordAttributes(); } return mBuffers->getLanguageModelDictContent()->getWordAttributes(prevWordIds, wordId, - mHeaderPolicy); + false /* mustMatchAllPrevWords */, mHeaderPolicy); } int Ver4PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds, @@ -118,18 +118,13 @@ int Ver4PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordI if (wordId == NOT_A_WORD_ID || prevWordIds.contains(NOT_A_WORD_ID)) { return NOT_A_PROBABILITY; } - const ProbabilityEntry probabilityEntry = - mBuffers->getLanguageModelDictContent()->getNgramProbabilityEntry(prevWordIds, wordId); - if (!probabilityEntry.isValid() || probabilityEntry.isBlacklisted() - || probabilityEntry.isNotAWord()) { + const WordAttributes wordAttributes = + mBuffers->getLanguageModelDictContent()->getWordAttributes(prevWordIds, wordId, + true /* mustMatchAllPrevWords */, mHeaderPolicy); + if (wordAttributes.isBlacklisted() || wordAttributes.isNotAWord()) { return NOT_A_PROBABILITY; } - if (mHeaderPolicy->hasHistoricalInfoOfWords()) { - return ForgettingCurveUtils::decodeProbability(probabilityEntry.getHistoricalInfo(), - mHeaderPolicy); - } else { - return probabilityEntry.getProbability(); - } + return wordAttributes.getProbability(); } BinaryDictionaryShortcutIterator Ver4PatriciaTriePolicy::getShortcutIterator( @@ -152,9 +147,7 @@ void Ver4PatriciaTriePolicy::iterateNgramEntries(const WordIdArrayView prevWordI continue; } const int probability = probabilityEntry.hasHistoricalInfo() ? - ForgettingCurveUtils::decodeProbability( - probabilityEntry.getHistoricalInfo(), mHeaderPolicy) : - probabilityEntry.getProbability(); + 0 : probabilityEntry.getProbability(); listener->onVisitEntry(probability, entry.getWordId()); } } @@ -386,25 +379,35 @@ bool Ver4PatriciaTriePolicy::updateEntriesForWordWithNgramContext( AKLOGE("Cannot add unigarm entry in updateEntriesForWordWithNgramContext()."); return false; } + if (!isValidWord) { + return true; + } wordId = getWordId(wordCodePoints, false /* tryLowerCaseSearch */); } WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray; const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */); - if (prevWordIds.firstOrDefault(NOT_A_WORD_ID) == NOT_A_WORD_ID - && ngramContext->isNthPrevWordBeginningOfSentence(1 /* n */)) { - const UnigramProperty beginningOfSentenceUnigramProperty( - true /* representsBeginningOfSentence */, - true /* isNotAWord */, false /* isPossiblyOffensive */, NOT_A_PROBABILITY, - HistoricalInfo(historicalInfo.getTimestamp(), 0 /* level */, 0 /* count */)); - if (!addUnigramEntry(ngramContext->getNthPrevWordCodePoints(1 /* n */), - &beginningOfSentenceUnigramProperty)) { - AKLOGE("Cannot add BoS entry in updateEntriesForWordWithNgramContext()."); + if (ngramContext->isNthPrevWordBeginningOfSentence(1 /* n */)) { + if (prevWordIds.firstOrDefault(NOT_A_WORD_ID) == NOT_A_WORD_ID) { + const UnigramProperty beginningOfSentenceUnigramProperty( + true /* representsBeginningOfSentence */, + true /* isNotAWord */, false /* isPossiblyOffensive */, NOT_A_PROBABILITY, + HistoricalInfo(historicalInfo.getTimestamp(), 0 /* level */, 0 /* count */)); + if (!addUnigramEntry(ngramContext->getNthPrevWordCodePoints(1 /* n */), + &beginningOfSentenceUnigramProperty)) { + AKLOGE("Cannot add BoS entry in updateEntriesForWordWithNgramContext()."); + return false; + } + // Refresh word ids. + ngramContext->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */); + } + // Update entries for beginning of sentence. + if (!mBuffers->getMutableLanguageModelDictContent()->updateAllEntriesOnInputWord( + prevWordIds.skip(1 /* n */), prevWordIds[0], true /* isVaild */, historicalInfo, + mHeaderPolicy, &mEntryCounters)) { return false; } - // Refresh word ids. - ngramContext->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */); } if (!mBuffers->getMutableLanguageModelDictContent()->updateAllEntriesOnInputWord(prevWordIds, wordId, updateAsAValidWord, historicalInfo, mHeaderPolicy, &mEntryCounters)) { @@ -542,7 +545,7 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty( } } const WordAttributes wordAttributes = languageModelDictContent->getWordAttributes( - WordIdArrayView(), wordId, mHeaderPolicy); + WordIdArrayView(), wordId, true /* mustMatchAllPrevWords */, mHeaderPolicy); const ProbabilityEntry probabilityEntry = languageModelDictContent->getProbabilityEntry(wordId); const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo(); const UnigramProperty unigramProperty(probabilityEntry.representsBeginningOfSentence(), diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp index 0cffe569d..8b47147e1 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp @@ -28,9 +28,11 @@ const size_t FormatUtils::DICTIONARY_MINIMUM_SIZE = 12; /* static */ FormatUtils::FORMAT_VERSION FormatUtils::getFormatVersion(const int formatVersion) { switch (formatVersion) { case VERSION_2: - return VERSION_2; case VERSION_201: - return VERSION_201; + AKLOGE("Dictionary versions 2 and 201 are incompatible with this version"); + return UNKNOWN_VERSION; + case VERSION_202: + return VERSION_202; case VERSION_4_ONLY_FOR_TESTING: return VERSION_4_ONLY_FOR_TESTING; case VERSION_4: diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h index 96310086b..05bd7eb8a 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h @@ -31,8 +31,12 @@ class FormatUtils { public: enum FORMAT_VERSION { // These MUST have the same values as the relevant constants in FormatSpec.java. + // TODO: Remove VERSION_2 and VERSION_201 when we: + // * Confirm that old versions of LatinIME download old-format dictionaries + // * We no longer need the corresponding constants on the Java side for dicttool VERSION_2 = 2, VERSION_201 = 201, + VERSION_202 = 202, VERSION_4_ONLY_FOR_TESTING = 399, VERSION_4 = 402, VERSION_4_DEV = 403, diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.cpp new file mode 100644 index 000000000..e8fa06942 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.cpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + +#include "suggest/policyimpl/dictionary/utils/probability_utils.h" + +namespace latinime { + +const float ProbabilityUtils::PROBABILITY_ENCODING_SCALER = 8.58923700372f; + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.h index 3b339e61a..2050af1e9 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.h +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.h @@ -17,6 +17,9 @@ #ifndef LATINIME_PROBABILITY_UTILS_H #define LATINIME_PROBABILITY_UTILS_H +#include <algorithm> +#include <cmath> + #include "defines.h" namespace latinime { @@ -47,8 +50,20 @@ class ProbabilityUtils { + static_cast<int>(static_cast<float>(bigramProbability + 1) * stepSize); } + // Encode probability using the same way as we are doing for main dictionaries. + static AK_FORCE_INLINE int encodeRawProbability(const float rawProbability) { + const float probability = static_cast<float>(MAX_PROBABILITY) + + log2f(rawProbability) * PROBABILITY_ENCODING_SCALER; + if (probability < 0.0f) { + return 0; + } + return std::min(static_cast<int>(probability + 0.5f), MAX_PROBABILITY); + } + private: DISALLOW_IMPLICIT_CONSTRUCTORS(ProbabilityUtils); + + static const float PROBABILITY_ENCODING_SCALER; }; } #endif /* LATINIME_PROBABILITY_UTILS_H */ diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp new file mode 100644 index 000000000..44b5a8aaa --- /dev/null +++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_global_counters.h" + +#include <gtest/gtest.h> + +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" + +namespace latinime { +namespace { + +TEST(LanguageModelDictContentGlobalCountersTest, TestUpdateMaxValueOfCounters) { + LanguageModelDictContentGlobalCounters globalCounters; + + EXPECT_FALSE(globalCounters.needsToHalveCounters()); + globalCounters.updateMaxValueOfCounters(10); + EXPECT_FALSE(globalCounters.needsToHalveCounters()); + const int count = (1 << (Ver4DictConstants::WORD_COUNT_FIELD_SIZE * CHAR_BIT)) - 1; + globalCounters.updateMaxValueOfCounters(count); + EXPECT_TRUE(globalCounters.needsToHalveCounters()); + globalCounters.halveCounters(); + EXPECT_FALSE(globalCounters.needsToHalveCounters()); +} + +TEST(LanguageModelDictContentGlobalCountersTest, TestIncrementTotalCount) { + LanguageModelDictContentGlobalCounters globalCounters; + + EXPECT_EQ(0, globalCounters.getTotalCount()); + globalCounters.incrementTotalCount(); + EXPECT_EQ(1, globalCounters.getTotalCount()); + for (int i = 1; i < 50; ++i) { + globalCounters.incrementTotalCount(); + } + EXPECT_EQ(50, globalCounters.getTotalCount()); + globalCounters.halveCounters(); + EXPECT_EQ(25, globalCounters.getTotalCount()); + globalCounters.halveCounters(); + EXPECT_EQ(12, globalCounters.getTotalCount()); + for (int i = 0; i < 4; ++i) { + globalCounters.halveCounters(); + } + EXPECT_EQ(0, globalCounters.getTotalCount()); +} + +} // namespace +} // namespace latinime diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp index 4469dc715..86040f12c 100644 --- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp +++ b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp @@ -108,14 +108,14 @@ TEST(LanguageModelDictContentTest, TestGetWordProbability) { languageModelDictContent.setNgramProbabilityEntry(prevWordIds.limit(1), wordId, &bigramProbabilityEntry); EXPECT_EQ(bigramProbability, languageModelDictContent.getWordAttributes(prevWordIds, wordId, - nullptr /* headerPolicy */).getProbability()); + false /* mustMatchAllPrevWords */, nullptr /* headerPolicy */).getProbability()); const ProbabilityEntry trigramProbabilityEntry(flag, trigramProbability); languageModelDictContent.setNgramProbabilityEntry(prevWordIds.limit(1), prevWordIds[1], &probabilityEntry); languageModelDictContent.setNgramProbabilityEntry(prevWordIds.limit(2), wordId, &trigramProbabilityEntry); EXPECT_EQ(trigramProbability, languageModelDictContent.getWordAttributes(prevWordIds, wordId, - nullptr /* headerPolicy */).getProbability()); + false /* mustMatchAllPrevWords */, nullptr /* headerPolicy */).getProbability()); } } // namespace diff --git a/native/jni/tests/suggest/policyimpl/dictionary/utils/probability_utils_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/utils/probability_utils_test.cpp new file mode 100644 index 000000000..be1f278c6 --- /dev/null +++ b/native/jni/tests/suggest/policyimpl/dictionary/utils/probability_utils_test.cpp @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#include "suggest/policyimpl/dictionary/utils/probability_utils.h" + +#include <gtest/gtest.h> + +#include "defines.h" + +namespace latinime { +namespace { + +TEST(ProbabilityUtilsTest, TestEncodeRawProbability) { + EXPECT_EQ(MAX_PROBABILITY, ProbabilityUtils::encodeRawProbability(1.0f)); + EXPECT_EQ(MAX_PROBABILITY - 9, ProbabilityUtils::encodeRawProbability(0.5f)); + EXPECT_EQ(0, ProbabilityUtils::encodeRawProbability(0.0f)); +} + +} // namespace +} // namespace latinime diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java index f90b266b6..b9764488e 100644 --- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java +++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java @@ -59,6 +59,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { super.setUp(); mCurrentTime = 0; mDictFilesToBeDeleted.clear(); + setCurrentTimeForTestMode(mCurrentTime); } @Override @@ -71,8 +72,8 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { super.tearDown(); } - private static boolean supportsBeginningOfSentence(final int formatVersion) { - return formatVersion > FormatSpec.VERSION401; + private static boolean supportsCountBasedNgram(final int formatVersion) { + return formatVersion >= FormatSpec.VERSION4_DEV; } private static boolean supportsNgram(final int formatVersion) { @@ -142,19 +143,13 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { private File createEmptyDictionaryWithAttributeMapAndGetFile(final int formatVersion, final HashMap<String, String> attributeMap) { - if (formatVersion == FormatSpec.VERSION4 - || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING - || formatVersion == FormatSpec.VERSION4_DEV) { - try { - final File dictFile = createEmptyVer4DictionaryAndGetFile(formatVersion, - attributeMap); - mDictFilesToBeDeleted.add(dictFile); - return dictFile; - } catch (final IOException e) { - fail(e.toString()); - } - } else { - fail("Dictionary format version " + formatVersion + " is not supported."); + try { + final File dictFile = createEmptyVer4DictionaryAndGetFile(formatVersion, + attributeMap); + mDictFilesToBeDeleted.add(dictFile); + return dictFile; + } catch (final IOException e) { + fail(e.toString()); } return null; } @@ -263,12 +258,10 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { onInputWord(binaryDictionary, "a", false /* isValidWord */); assertTrue(binaryDictionary.isValidWord("a")); - onInputWord(binaryDictionary, "b", true /* isValidWord */); - assertTrue(binaryDictionary.isValidWord("b")); - onInputWordWithPrevWord(binaryDictionary, "b", false /* isValidWord */, "a"); assertFalse(isValidBigram(binaryDictionary, "a", "b")); onInputWordWithPrevWord(binaryDictionary, "b", false /* isValidWord */, "a"); + assertTrue(binaryDictionary.isValidWord("b")); assertTrue(isValidBigram(binaryDictionary, "a", "b")); onInputWordWithPrevWord(binaryDictionary, "c", true /* isValidWord */, "a"); @@ -284,16 +277,12 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { return; } - onInputWordWithPrevWords(binaryDictionary, "c", false /* isValidWord */, "b", "a"); - assertFalse(isValidTrigram(binaryDictionary, "a", "b", "c")); - assertFalse(isValidBigram(binaryDictionary, "b", "c")); - onInputWordWithPrevWords(binaryDictionary, "c", false /* isValidWord */, "b", "a"); + onInputWordWithPrevWords(binaryDictionary, "c", true /* isValidWord */, "b", "a"); assertTrue(isValidTrigram(binaryDictionary, "a", "b", "c")); assertTrue(isValidBigram(binaryDictionary, "b", "c")); - - onInputWordWithPrevWords(binaryDictionary, "d", true /* isValidWord */, "b", "a"); - assertTrue(isValidTrigram(binaryDictionary, "a", "b", "d")); - assertTrue(isValidBigram(binaryDictionary, "b", "d")); + onInputWordWithPrevWords(binaryDictionary, "d", false /* isValidWord */, "c", "b"); + assertFalse(isValidTrigram(binaryDictionary, "b", "c", "d")); + assertFalse(isValidBigram(binaryDictionary, "c", "d")); onInputWordWithPrevWords(binaryDictionary, "cd", true /* isValidWord */, "b", "a"); assertTrue(isValidTrigram(binaryDictionary, "a", "b", "cd")); @@ -312,6 +301,13 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { onInputWord(binaryDictionary, "a", true /* isValidWord */); assertTrue(binaryDictionary.isValidWord("a")); forcePassingShortTime(binaryDictionary); + if (supportsCountBasedNgram(formatVersion)) { + // Count based ngram language model doesn't support decaying based on the elapsed time. + assertTrue(binaryDictionary.isValidWord("a")); + } else { + assertFalse(binaryDictionary.isValidWord("a")); + } + forcePassingLongTime(binaryDictionary); assertFalse(binaryDictionary.isValidWord("a")); onInputWord(binaryDictionary, "a", true /* isValidWord */); @@ -327,6 +323,12 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { onInputWordWithPrevWord(binaryDictionary, "b", true /* isValidWord */, "a"); assertTrue(isValidBigram(binaryDictionary, "a", "b")); forcePassingShortTime(binaryDictionary); + if (supportsCountBasedNgram(formatVersion)) { + assertTrue(isValidBigram(binaryDictionary, "a", "b")); + } else { + assertFalse(isValidBigram(binaryDictionary, "a", "b")); + } + forcePassingLongTime(binaryDictionary); assertFalse(isValidBigram(binaryDictionary, "a", "b")); onInputWord(binaryDictionary, "a", true /* isValidWord */); @@ -349,7 +351,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { onInputWordWithPrevWord(binaryDictionary, "bc", true /* isValidWord */, "ab"); onInputWordWithPrevWords(binaryDictionary, "cd", true /* isValidWord */, "bc", "ab"); assertTrue(isValidTrigram(binaryDictionary, "ab", "bc", "cd")); - forcePassingShortTime(binaryDictionary); + forcePassingLongTime(binaryDictionary); assertFalse(isValidTrigram(binaryDictionary, "ab", "bc", "cd")); onInputWord(binaryDictionary, "ab", true /* isValidWord */); @@ -540,7 +542,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { assertTrue(bigramCountBeforeGC > bigramCountAfterGC); } } - + forcePassingShortTime(binaryDictionary); assertTrue(Integer.parseInt(binaryDictionary.getPropertyForGettingStats( BinaryDictionary.BIGRAM_COUNT_QUERY)) > 0); assertTrue(Integer.parseInt(binaryDictionary.getPropertyForGettingStats( @@ -666,14 +668,17 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { assertEquals(toFormatVersion, binaryDictionary.getFormatVersion()); assertTrue(binaryDictionary.isValidWord("aaa")); assertFalse(binaryDictionary.isValidWord("bbb")); - assertTrue(binaryDictionary.getFrequency("aaa") < binaryDictionary.getFrequency("ccc")); - onInputWord(binaryDictionary, "bbb", false /* isValidWord */); - assertTrue(binaryDictionary.isValidWord("bbb")); + if (supportsCountBasedNgram(toFormatVersion)) { + assertTrue(binaryDictionary.getFrequency("aaa") < binaryDictionary.getFrequency("ccc")); + onInputWord(binaryDictionary, "bbb", false /* isValidWord */); + assertTrue(binaryDictionary.isValidWord("bbb")); + } assertTrue(isValidBigram(binaryDictionary, "aaa", "abc")); assertFalse(isValidBigram(binaryDictionary, "aaa", "bbb")); - onInputWordWithPrevWord(binaryDictionary, "bbb", false /* isValidWord */, "aaa"); - assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb")); - + if (supportsCountBasedNgram(toFormatVersion)) { + onInputWordWithPrevWord(binaryDictionary, "bbb", false /* isValidWord */, "aaa"); + assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb")); + } if (supportsNgram(toFormatVersion)) { assertTrue(isValidTrigram(binaryDictionary, "aaa", "abc", "xyz")); assertFalse(isValidTrigram(binaryDictionary, "aaa", "abc", "def")); @@ -686,9 +691,7 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { public void testBeginningOfSentence() { for (final int formatVersion : DICT_FORMAT_VERSIONS) { - if (supportsBeginningOfSentence(formatVersion)) { - testBeginningOfSentence(formatVersion); - } + testBeginningOfSentence(formatVersion); } } @@ -716,10 +719,8 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa")); assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "bbb")); onInputWordWithBeginningOfSentenceContext(binaryDictionary, "aaa", true /* isValidWord */); - assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa")); onInputWordWithBeginningOfSentenceContext(binaryDictionary, "aaa", true /* isValidWord */); onInputWordWithBeginningOfSentenceContext(binaryDictionary, "bbb", true /* isValidWord */); - assertFalse(binaryDictionary.isValidNgram(beginningOfSentenceContext, "bbb")); onInputWordWithBeginningOfSentenceContext(binaryDictionary, "bbb", true /* isValidWord */); assertTrue(binaryDictionary.isValidNgram(beginningOfSentenceContext, "aaa")); assertTrue(binaryDictionary.isValidNgram(beginningOfSentenceContext, "bbb")); diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java index a35fa13ce..d239f8dac 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java @@ -314,14 +314,14 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { final String dictVersion = Long.toString(System.currentTimeMillis()); final String codePointTableAttribute = DictionaryHeader.CODE_POINT_TABLE_KEY; final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, - BinaryDictUtils.VERSION201_OPTIONS, getContext().getCacheDir()); + BinaryDictUtils.STATIC_OPTIONS, getContext().getCacheDir()); // Write a test dictionary final DictEncoder dictEncoder = new Ver2DictEncoder(file, Ver2DictEncoder.CODE_POINT_TABLE_ON); final FormatSpec.FormatOptions formatOptions = new FormatSpec.FormatOptions( - FormatSpec.MINIMUM_SUPPORTED_VERSION_OF_CODE_POINT_TABLE); + FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION); final FusionDictionary sourcedict = new FusionDictionary(new PtNodeArray(), BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions)); addUnigrams(words.size(), sourcedict, words, null /* shortcutMap */); @@ -359,11 +359,11 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { final List<String> results = new ArrayList<>(); runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER, - BinaryDictUtils.VERSION2_OPTIONS); + BinaryDictUtils.STATIC_OPTIONS); runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER, - BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP); + BinaryDictUtils.DYNAMIC_OPTIONS_WITHOUT_TIMESTAMP); runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER, - BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP); + BinaryDictUtils.DYNAMIC_OPTIONS_WITH_TIMESTAMP); for (final String result : results) { Log.d(TAG, result); } @@ -373,11 +373,11 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { final List<String> results = new ArrayList<>(); runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY, - BinaryDictUtils.VERSION2_OPTIONS); + BinaryDictUtils.STATIC_OPTIONS); runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY, - BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP); + BinaryDictUtils.DYNAMIC_OPTIONS_WITHOUT_TIMESTAMP); runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY, - BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP); + BinaryDictUtils.DYNAMIC_OPTIONS_WITH_TIMESTAMP); for (final String result : results) { Log.d(TAG, result); @@ -501,7 +501,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { final ArrayList<String> results = new ArrayList<>(); runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER, - BinaryDictUtils.VERSION2_OPTIONS); + BinaryDictUtils.STATIC_OPTIONS); for (final String result : results) { Log.d(TAG, result); @@ -512,7 +512,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { final ArrayList<String> results = new ArrayList<>(); runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY, - BinaryDictUtils.VERSION2_OPTIONS); + BinaryDictUtils.STATIC_OPTIONS); for (final String result : results) { Log.d(TAG, result); @@ -623,9 +623,9 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { final ArrayList<String> results = new ArrayList<>(); runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY, - BinaryDictUtils.VERSION2_OPTIONS); + BinaryDictUtils.STATIC_OPTIONS); runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER, - BinaryDictUtils.VERSION2_OPTIONS); + BinaryDictUtils.STATIC_OPTIONS); for (final String result : results) { Log.d(TAG, result); @@ -633,7 +633,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { } public void testVer2DictGetWordProperty() { - final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS; + final FormatOptions formatOptions = BinaryDictUtils.STATIC_OPTIONS; final ArrayList<String> words = sWords; final HashMap<String, List<String>> shortcuts = sShortcuts; final String dictName = "testGetWordProperty"; @@ -669,7 +669,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase { } public void testVer2DictIteration() { - final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS; + final FormatOptions formatOptions = BinaryDictUtils.STATIC_OPTIONS; final ArrayList<String> words = sWords; final HashMap<String, List<String>> shortcuts = sShortcuts; final SparseArray<List<Integer>> bigrams = sEmptyBigrams; diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java index 60e38250f..ce905c499 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java @@ -819,12 +819,18 @@ public class BinaryDictEncoderUtils { final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray) throws IOException, UnsupportedFormatException { final int version = formatOptions.mVersion; - if (version < FormatSpec.MINIMUM_SUPPORTED_VERSION - || version > FormatSpec.MAXIMUM_SUPPORTED_VERSION) { + if ((version >= FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION && + version <= FormatSpec.MAXIMUM_SUPPORTED_STATIC_VERSION) || ( + version >= FormatSpec.MINIMUM_SUPPORTED_DYNAMIC_VERSION && + version <= FormatSpec.MAXIMUM_SUPPORTED_DYNAMIC_VERSION)) { + // Dictionary is valid + } else { throw new UnsupportedFormatException("Requested file format version " + version - + ", but this implementation only supports versions " - + FormatSpec.MINIMUM_SUPPORTED_VERSION + " through " - + FormatSpec.MAXIMUM_SUPPORTED_VERSION); + + ", but this implementation only supports static versions " + + FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION + " through " + + FormatSpec.MAXIMUM_SUPPORTED_STATIC_VERSION + " and dynamic versions " + + FormatSpec.MINIMUM_SUPPORTED_DYNAMIC_VERSION + " through " + + FormatSpec.MAXIMUM_SUPPORTED_DYNAMIC_VERSION); } ByteArrayOutputStream headerBuffer = new ByteArrayOutputStream(256); diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java index 8eabf749d..9c1e4cf84 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java +++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java @@ -28,13 +28,11 @@ public class BinaryDictUtils { public static final String TEST_DICT_FILE_EXTENSION = ".testDict"; - public static final FormatSpec.FormatOptions VERSION2_OPTIONS = - new FormatSpec.FormatOptions(FormatSpec.VERSION2); - public static final FormatSpec.FormatOptions VERSION201_OPTIONS = - new FormatSpec.FormatOptions(FormatSpec.VERSION201); - public static final FormatSpec.FormatOptions VERSION4_OPTIONS_WITHOUT_TIMESTAMP = + public static final FormatSpec.FormatOptions STATIC_OPTIONS = + new FormatSpec.FormatOptions(FormatSpec.VERSION202); + public static final FormatSpec.FormatOptions DYNAMIC_OPTIONS_WITHOUT_TIMESTAMP = new FormatSpec.FormatOptions(FormatSpec.VERSION4, false /* hasTimestamp */); - public static final FormatSpec.FormatOptions VERSION4_OPTIONS_WITH_TIMESTAMP = + public static final FormatSpec.FormatOptions DYNAMIC_OPTIONS_WITH_TIMESTAMP = new FormatSpec.FormatOptions(FormatSpec.VERSION4, true /* hasTimestamp */); public static DictionaryOptions makeDictionaryOptions(final String id, final String version, @@ -55,7 +53,8 @@ public class BinaryDictUtils { public static File getDictFile(final String name, final String version, final FormatOptions formatOptions, final File directory) { if (formatOptions.mVersion == FormatSpec.VERSION2 - || formatOptions.mVersion == FormatSpec.VERSION201) { + || formatOptions.mVersion == FormatSpec.VERSION201 + || formatOptions.mVersion == FormatSpec.VERSION202) { return new File(directory, name + "." + version + TEST_DICT_FILE_EXTENSION); } else if (formatOptions.mVersion == FormatSpec.VERSION4) { return new File(directory, name + "." + version); @@ -71,7 +70,7 @@ public class BinaryDictUtils { file.mkdir(); } return new Ver4DictEncoder(file); - } else if (formatOptions.mVersion == FormatSpec.VERSION2) { + } else if (formatOptions.mVersion == FormatSpec.VERSION202) { return new Ver2DictEncoder(file, Ver2DictEncoder.CODE_POINT_TABLE_OFF); } else { throw new RuntimeException("The format option has a wrong version : " diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java index 457e7af8e..5c261a94d 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java +++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java @@ -178,7 +178,8 @@ public class Ver2DictDecoder extends AbstractDictDecoder { throw new IOException("Cannot read the dictionary header."); } if (header.mFormatOptions.mVersion != FormatSpec.VERSION2 && - header.mFormatOptions.mVersion != FormatSpec.VERSION201) { + header.mFormatOptions.mVersion != FormatSpec.VERSION201 && + header.mFormatOptions.mVersion != FormatSpec.VERSION202) { throw new UnsupportedFormatException("File header has a wrong version : " + header.mFormatOptions.mVersion); } diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java index 2c2152be7..b52b8c485 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java +++ b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java @@ -124,7 +124,8 @@ public class Ver2DictEncoder implements DictEncoder { @Override public void writeDictionary(final FusionDictionary dict, final FormatOptions formatOptions) throws IOException, UnsupportedFormatException { - if (formatOptions.mVersion > FormatSpec.VERSION201) { + // We no longer support anything but the latest version of v2. + if (formatOptions.mVersion != FormatSpec.VERSION202) { throw new UnsupportedFormatException( "The given format options has wrong version number : " + formatOptions.mVersion); diff --git a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java index a5979c3df..dc4e2e4bb 100644 --- a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java @@ -29,14 +29,45 @@ import java.util.Collections; @SmallTest public class CollectionUtilsTests extends AndroidTestCase { /** + * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} fails as expected + * with some invalid inputs. + */ + public void testArrayAsListFailure() { + final String[] array = { "0", "1" }; + // Negative start + try { + CollectionUtils.arrayAsList(array, -1, 1); + fail("Failed to catch start < 0"); + } catch (final IllegalArgumentException e) { + assertEquals("Invalid start: -1 end: 1 with array.length: 2", e.getMessage()); + } + // start > end + try { + CollectionUtils.arrayAsList(array, 1, -1); + fail("Failed to catch start > end"); + } catch (final IllegalArgumentException e) { + assertEquals("Invalid start: 1 end: -1 with array.length: 2", e.getMessage()); + } + // end > array.length + try { + CollectionUtils.arrayAsList(array, 1, 3); + fail("Failed to catch end > array.length"); + } catch (final IllegalArgumentException e) { + assertEquals("Invalid start: 1 end: 3 with array.length: 2", e.getMessage()); + } + } + + /** * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} gives the expected * results for a few valid inputs. */ public void testArrayAsList() { - final String[] array = { "0", "1", "2", "3", "4" }; final ArrayList<String> empty = new ArrayList<>(); + assertEquals(empty, CollectionUtils.arrayAsList(new String[] { }, 0, 0)); + final String[] array = { "0", "1", "2", "3", "4" }; assertEquals(empty, CollectionUtils.arrayAsList(array, 0, 0)); assertEquals(empty, CollectionUtils.arrayAsList(array, 1, 1)); + assertEquals(empty, CollectionUtils.arrayAsList(array, array.length, array.length)); final ArrayList<String> expected123 = new ArrayList<>(Arrays.asList("1", "2", "3")); assertEquals(expected123, CollectionUtils.arrayAsList(array, 1, 4)); } diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java index 48d2e5922..955c5728c 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java @@ -98,6 +98,7 @@ public class CombinedInputOutput { String word = null; ProbabilityInfo probabilityInfo = new ProbabilityInfo(0); boolean isNotAWord = false; + boolean isPossiblyOffensive = false; ArrayList<WeightedString> bigrams = new ArrayList<>(); ArrayList<WeightedString> shortcuts = new ArrayList<>(); while (null != (line = reader.readLine())) { @@ -106,7 +107,7 @@ public class CombinedInputOutput { if (args[0].matches(CombinedFormatUtils.WORD_TAG + "=.*")) { if (null != word) { dict.add(word, probabilityInfo, shortcuts.isEmpty() ? null : shortcuts, - isNotAWord, false /* isPossiblyOffensive */); + isNotAWord, isPossiblyOffensive); for (WeightedString s : bigrams) { dict.setBigram(word, s.mWord, s.mProbabilityInfo); } @@ -114,27 +115,37 @@ public class CombinedInputOutput { if (!shortcuts.isEmpty()) shortcuts = new ArrayList<>(); if (!bigrams.isEmpty()) bigrams = new ArrayList<>(); isNotAWord = false; + isPossiblyOffensive = false; for (String param : args) { final String params[] = param.split("=", 2); if (2 != params.length) throw new RuntimeException("Wrong format : " + line); - if (CombinedFormatUtils.WORD_TAG.equals(params[0])) { - word = params[1]; - } else if (CombinedFormatUtils.PROBABILITY_TAG.equals(params[0])) { - probabilityInfo = new ProbabilityInfo(Integer.parseInt(params[1]), - probabilityInfo.mTimestamp, probabilityInfo.mLevel, - probabilityInfo.mCount); - } else if (CombinedFormatUtils.HISTORICAL_INFO_TAG.equals(params[0])) { - final String[] historicalInfoParams = - params[1].split(CombinedFormatUtils.HISTORICAL_INFO_SEPARATOR); - if (historicalInfoParams.length != HISTORICAL_INFO_ELEMENT_COUNT) { - throw new RuntimeException("Wrong format (historical info) : " + line); - } - probabilityInfo = new ProbabilityInfo(probabilityInfo.mProbability, - Integer.parseInt(historicalInfoParams[0]), - Integer.parseInt(historicalInfoParams[1]), - Integer.parseInt(historicalInfoParams[2])); - } else if (CombinedFormatUtils.NOT_A_WORD_TAG.equals(params[0])) { - isNotAWord = "true".equals(params[1]); + switch (params[0]) { + case CombinedFormatUtils.WORD_TAG: + word = params[1]; + break; + case CombinedFormatUtils.PROBABILITY_TAG: + probabilityInfo = new ProbabilityInfo(Integer.parseInt(params[1]), + probabilityInfo.mTimestamp, probabilityInfo.mLevel, + probabilityInfo.mCount); + break; + case CombinedFormatUtils.HISTORICAL_INFO_TAG: + final String[] historicalInfoParams = params[1].split( + CombinedFormatUtils.HISTORICAL_INFO_SEPARATOR); + if (historicalInfoParams.length != HISTORICAL_INFO_ELEMENT_COUNT) { + throw new RuntimeException("Wrong format (historical info) : " + + line); + } + probabilityInfo = new ProbabilityInfo(probabilityInfo.mProbability, + Integer.parseInt(historicalInfoParams[0]), + Integer.parseInt(historicalInfoParams[1]), + Integer.parseInt(historicalInfoParams[2])); + break; + case CombinedFormatUtils.NOT_A_WORD_TAG: + isNotAWord = CombinedFormatUtils.isLiteralTrue(params[1]); + break; + case CombinedFormatUtils.POSSIBLY_OFFENSIVE_TAG: + isPossiblyOffensive = CombinedFormatUtils.isLiteralTrue(params[1]); + break; } } } else if (args[0].matches(CombinedFormatUtils.SHORTCUT_TAG + "=.*")) { @@ -190,7 +201,7 @@ public class CombinedInputOutput { } if (null != word) { dict.add(word, probabilityInfo, shortcuts.isEmpty() ? null : shortcuts, isNotAWord, - false /* isPossiblyOffensive */); + isPossiblyOffensive); for (WeightedString s : bigrams) { dict.setBigram(word, s.mWord, s.mProbabilityInfo); } 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 8f9e4a3a6..6187853c8 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java @@ -120,7 +120,7 @@ public class DictionaryMaker { String inputCombined = null; String outputBinary = null; String outputCombined = null; - int outputBinaryFormatVersion = FormatSpec.VERSION201; // the default version is 201. + int outputBinaryFormatVersion = FormatSpec.VERSION202; // the default version is 202. // Don't use code point table by default. int codePointTableMode = Ver2DictEncoder.CODE_POINT_TABLE_OFF; |