aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/raw/setup_welcome_image.pngbin117980 -> 50389 bytes
-rw-r--r--java/res/raw/setup_welcome_video.mp4bin459085 -> 549513 bytes
-rw-r--r--java/res/values-af/strings.xml6
-rw-r--r--java/res/values-am/strings.xml8
-rw-r--r--java/res/values-ar/strings.xml6
-rw-r--r--java/res/values-be/strings.xml4
-rw-r--r--java/res/values-bg/strings.xml6
-rw-r--r--java/res/values-ca/strings.xml6
-rw-r--r--java/res/values-cs/strings.xml6
-rw-r--r--java/res/values-da/strings.xml8
-rw-r--r--java/res/values-de/strings.xml6
-rw-r--r--java/res/values-el/strings.xml6
-rw-r--r--java/res/values-en-rGB/strings.xml6
-rw-r--r--java/res/values-en-rIN/strings-appname.xml27
-rw-r--r--java/res/values-en-rIN/strings.xml246
-rw-r--r--java/res/values-es-rUS/strings.xml6
-rw-r--r--java/res/values-es/strings.xml10
-rw-r--r--java/res/values-et-rEE/strings.xml6
-rw-r--r--java/res/values-fa/strings.xml6
-rw-r--r--java/res/values-fi/strings.xml6
-rw-r--r--java/res/values-fr-rCA/strings-appname.xml27
-rw-r--r--java/res/values-fr-rCA/strings.xml255
-rw-r--r--java/res/values-fr/strings.xml6
-rw-r--r--java/res/values-hi/strings.xml6
-rw-r--r--java/res/values-hr/strings.xml6
-rw-r--r--java/res/values-hu/strings.xml6
-rw-r--r--java/res/values-hy-rAM/strings-appname.xml27
-rw-r--r--java/res/values-hy-rAM/strings.xml246
-rw-r--r--java/res/values-in/strings.xml6
-rw-r--r--java/res/values-it/strings.xml10
-rw-r--r--java/res/values-iw/strings.xml6
-rw-r--r--java/res/values-ja/strings.xml8
-rw-r--r--java/res/values-ka-rGE/strings.xml6
-rw-r--r--java/res/values-km-rKH/strings-appname.xml27
-rw-r--r--java/res/values-km-rKH/strings.xml246
-rw-r--r--java/res/values-ko/strings.xml6
-rw-r--r--java/res/values-lo-rLA/strings-appname.xml27
-rw-r--r--java/res/values-lo-rLA/strings.xml246
-rw-r--r--java/res/values-lt/strings.xml6
-rw-r--r--java/res/values-lv/strings.xml6
-rw-r--r--java/res/values-mn-rMN/strings.xml6
-rw-r--r--java/res/values-ms-rMY/strings.xml6
-rw-r--r--java/res/values-nb/strings.xml8
-rw-r--r--java/res/values-nl/strings.xml6
-rw-r--r--java/res/values-pl/strings.xml6
-rw-r--r--java/res/values-pt-rPT/strings.xml6
-rw-r--r--java/res/values-pt/strings.xml6
-rw-r--r--java/res/values-rm/strings.xml4
-rw-r--r--java/res/values-ro/strings.xml6
-rw-r--r--java/res/values-ru/strings.xml6
-rw-r--r--java/res/values-sk/strings.xml6
-rw-r--r--java/res/values-sl/strings.xml6
-rw-r--r--java/res/values-sr/strings.xml6
-rw-r--r--java/res/values-sv/strings.xml6
-rw-r--r--java/res/values-sw/strings.xml6
-rw-r--r--java/res/values-th/strings.xml6
-rw-r--r--java/res/values-tl/strings.xml6
-rw-r--r--java/res/values-tr/strings.xml6
-rw-r--r--java/res/values-uk/strings.xml6
-rw-r--r--java/res/values-vi/strings.xml6
-rw-r--r--java/res/values-zh-rCN/strings.xml6
-rw-r--r--java/res/values-zh-rHK/strings-appname.xml27
-rw-r--r--java/res/values-zh-rHK/strings.xml246
-rw-r--r--java/res/values-zh-rTW/strings.xml16
-rw-r--r--java/res/values-zu/strings.xml6
-rw-r--r--java/res/xml-sw600dp/rows_swiss.xml63
-rw-r--r--java/res/xml/kbd_swiss.xml26
-rw-r--r--java/res/xml/keyboard_layout_set_swiss.xml42
-rw-r--r--java/res/xml/method.xml16
-rw-r--r--java/res/xml/rowkeys_swiss1.xml29
-rw-r--r--java/res/xml/rowkeys_swiss2.xml32
-rw-r--r--java/res/xml/rows_swiss.xml57
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java1214
-rw-r--r--java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java3
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java6
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java1
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java6
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java105
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java3
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java67
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java21
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java66
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/DictDecoder.java3
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java35
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FormatSpec.java41
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/SparseTableContentReader.java120
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/SparseTableContentUpdater.java123
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/SparseTableContentWriter.java93
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java309
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java164
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java716
-rw-r--r--java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java4
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java62
-rw-r--r--native/jni/Android.mk17
-rw-r--r--native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp8
-rw-r--r--native/jni/src/defines.h20
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node.h79
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_utils.cpp42
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_utils.h12
-rw-r--r--native/jni/src/suggest/core/dicnode/dic_node_vector.h12
-rw-r--r--native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h79
-rw-r--r--native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h16
-rw-r--r--native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h41
-rw-r--r--native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp4
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.cpp40
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.h26
-rw-r--r--native/jni/src/suggest/core/dictionary/error_type_utils.cpp34
-rw-r--r--native/jni/src/suggest/core/dictionary/error_type_utils.h69
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info.cpp16
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info.h11
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_state.cpp6
-rw-r--r--native/jni/src/suggest/core/layout/proximity_info_state.h2
-rw-r--r--native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h7
-rw-r--r--native/jni/src/suggest/core/policy/weighting.cpp5
-rw-r--r--native/jni/src/suggest/core/policy/weighting.h3
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.cpp8
-rw-r--r--native/jni/src/suggest/core/session/dic_traverse_session.h27
-rw-r--r--native/jni/src/suggest/core/suggest.cpp22
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.cpp23
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.cpp53
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp124
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h163
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h4
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp3
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp78
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h (renamed from native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h)6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h185
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h39
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.cpp)29
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h (renamed from native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h)21
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/patricia_trie_reading_utils.cpp)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h (renamed from native/jni/src/suggest/policyimpl/dictionary/patricia_trie_reading_utils.h)0
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.cpp)62
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.h (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.h)19
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.cpp107
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h62
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp)140
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.h (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h)26
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.cpp)66
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.h)171
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.cpp)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h)0
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp)187
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h)21
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.cpp (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.cpp)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h (renamed from native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h)2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dict_content.h36
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h49
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h69
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h75
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp35
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h43
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp96
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h96
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h11
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp11
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.h50
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp2
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h1
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp99
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.h60
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_traversal.h4
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp47
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.h3
-rw-r--r--native/jni/src/utils/exclusive_ownership_pointer.h91
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTests.java2
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java223
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java152
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java86
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java30
-rw-r--r--tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml12
-rw-r--r--tools/make-keyboard-text/res/values-fr/donottranslate-more-keys.xml12
-rw-r--r--tools/make-keyboard-text/res/values/donottranslate-more-keys.xml6
176 files changed, 6562 insertions, 2450 deletions
diff --git a/java/res/raw/setup_welcome_image.png b/java/res/raw/setup_welcome_image.png
index 2445915b8..98e731331 100644
--- a/java/res/raw/setup_welcome_image.png
+++ b/java/res/raw/setup_welcome_image.png
Binary files differ
diff --git a/java/res/raw/setup_welcome_video.mp4 b/java/res/raw/setup_welcome_video.mp4
index 820852531..224bf250c 100644
--- a/java/res/raw/setup_welcome_video.mp4
+++ b/java/res/raw/setup_welcome_video.mp4
Binary files differ
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index a3c95b290..adf9e5bf5 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Koppel \'n kopstuk om te hoor hoe wagwoordsleutels hardop gesê word."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Huidige teks is %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Geen teks ingevoer nie"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> korrigeer <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> voer outokorreksie uit"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Sleutelkode %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aan (tik om te deaktiveer)"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 89e37b274..42f60a41f 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"የይለፍቃል ቁልፎች ጮክ በለው ሲነገሩ ለመስማት የጆሮ ማዳመጫ ሰካ::"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"የአሁኑ ፅሁፍ %s ነው"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"ምንም ፅሁፍ አልገባም"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>ን ወደ <xliff:g id="CORRECTED">%3$s</xliff:g> ያርመዋል"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> ራስ-ሰር እርማትን ያከናውናል"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"የቁልፍ ኮድ%d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"ቀይር"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"ቅያር በርቷል (ለማሰናክል ንካ)"</string>
@@ -163,7 +161,7 @@
<string name="save" msgid="7646738597196767214">"አስቀምጥ"</string>
<string name="subtype_locale" msgid="8576443440738143764">"ቋንቋ"</string>
<string name="keyboard_layout_set" msgid="4309233698194565609">"አቀማመጥ"</string>
- <string name="custom_input_style_note_message" msgid="8826731320846363423">"የተበጀው የግብዓት ቅጥህን ከመጠቀምህ በፊት መንቃት አለበት። አሁን ማንቃት ትፈልጋለህ?"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"የተበጀው የእርስዎን ግብዓት ቅጥ ከመጠቀምዎ በፊት መንቃት አለበት። አሁን ማንቃት ይፈልጋሉ?"</string>
<string name="enable" msgid="5031294444630523247">"አንቃ"</string>
<string name="not_now" msgid="6172462888202790482">"አሁን አልፈልግም"</string>
<string name="custom_input_style_already_exists" msgid="8008728952215449707">"ተመሳሳዩ የግብዓት ቅጥ አስቀድሞ አለ፦ <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index 9c3ff51c8..1d58832f4 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"يمكنك توصيل سماعة رأس لسماع مفاتيح كلمة المرور منطوقة بصوت عالٍ."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"النص الحالي هو %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"لم يتم إدخال نص"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> لتصحيح <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> إلى <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> للتصحيح التلقائي"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"رمز المفتاح %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"العالي"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift يعمل (انقر للتعطيل)"</string>
diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml
index 9e591dea9..d9b970807 100644
--- a/java/res/values-be/strings.xml
+++ b/java/res/values-be/strings.xml
@@ -87,9 +87,9 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Каб праслухаць паролi, падключыце гарнiтуру."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Бягучы тэкст %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Тэкст не ўведзены"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
+ <!-- no translation found for spoken_auto_correct (8005997889020109763) -->
<skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
+ <!-- no translation found for spoken_auto_correct_obscured (6276420476908833791) -->
<skip />
<string name="spoken_description_unknown" msgid="3197434010402179157">"Клавішны код %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Зрух"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index c21b53490..eecc0f0e0 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Включете слушалки, за да чуете клавишите за паролата на висок глас."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Текущият текст е %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Няма въведен текст"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"„<xliff:g id="KEY">%1$s</xliff:g>“ коригира „<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>“ на „<xliff:g id="CORRECTED">%3$s</xliff:g>“"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"„<xliff:g id="KEY">%1$s</xliff:g>“ изпълнява автоматично коригиране"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Код на клавишa %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"„Shift“ е включен (докоснете за деактивиране)"</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index d791452d4..ad3c92e68 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Connecta un auricular per escoltar les claus de la contrasenya en veu alta."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"El text actual és %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"No s\'ha introduït cap text"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> corregeix <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> per <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> aplica correccions automàtiques"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Clau de codi %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Maj"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Maj activat (pica per desactivar)"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index 2cd159d0f..930d30595 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Chcete-li slyšet, které klávesy jste při zadávání hesla stiskli, připojte sluchátka."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Aktuální text je %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Není zadán žádný text"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Klávesou <xliff:g id="KEY">%1$s</xliff:g> opravíte <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Klávesa <xliff:g id="KEY">%1$s</xliff:g> provádí automatickou opravu"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Kód klávesy %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Klávesa Shift je zapnutá (vypnete ji klepnutím)."</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index 6c9d9d786..93d5c4e9b 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Tilslut et headset for at høre indtastningen blive læst højt ved angivelse af adgangskode."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Nuværende tekst er %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Der er ingen indtastet tekst"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> retter <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> til <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> udfører automatisk rettelse"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Tastekode %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift-tast"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Skift er slået til (tryk for at deaktivere)"</string>
@@ -194,7 +192,7 @@
<string name="setup_step3_action" msgid="600879797256942259">"Konfigurer flere sprog"</string>
<string name="setup_finish_action" msgid="276559243409465389">"Afslut"</string>
<string name="show_setup_wizard_icon" msgid="5008028590593710830">"Vis appikon"</string>
- <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Vis appikon på applikationsliste"</string>
+ <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Vis appikon på applisten"</string>
<string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
<string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
<string name="dictionary_service_name" msgid="6237472350693511448">"Ordbogstjeneste"</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index 1a4e38542..ac5192623 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Schließen Sie ein Headset an, um das Passwort gesprochen zu hören."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Aktueller Text lautet %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Kein Text eingegeben"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Mit <xliff:g id="KEY">%1$s</xliff:g> wird <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> zu <xliff:g id="CORRECTED">%3$s</xliff:g> korrigiert."</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Mit <xliff:g id="KEY">%1$s</xliff:g> erfolgt eine Autokorrektur."</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Tastencode %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Umschalttaste"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Umschalttaste aktiviert (zum Deaktivieren berühren)"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index c2ee2d39b..54b3c3efa 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Συνδέστε ένα σετ ακουστικών για να ακούσετε τα πλήκτρα του κωδικού πρόσβασης να εκφωνούνται δυνατά."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Το τρέχον κείμενο είναι %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Δεν υπάρχει κείμενο"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> διορθώνει το <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> σε <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> εκτελεί αυτόματη διόρθωση"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Κωδικός πλήκτρου %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Το Shift είναι ενεργοποιημένο (πατήστε για απενεργοποίηση)"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 0586bcca4..bdffb94c1 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Plug in a headset to hear password keys spoken aloud."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Current text is %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"No text entered"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> corrects <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> to <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> performs auto-correction"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Key code %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift on (tap to disable)"</string>
diff --git a/java/res/values-en-rIN/strings-appname.xml b/java/res/values-en-rIN/strings-appname.xml
new file mode 100644
index 000000000..5ad5eae66
--- /dev/null
+++ b/java/res/values-en-rIN/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"Android Keyboard (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"Android Spell Checker (AOSP)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"Android Keyboard Settings (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"Android Spell Checker Settings (AOSP)"</string>
+</resources>
diff --git a/java/res/values-en-rIN/strings.xml b/java/res/values-en-rIN/strings.xml
new file mode 100644
index 000000000..bdffb94c1
--- /dev/null
+++ b/java/res/values-en-rIN/strings.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Look up contact names"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Spell checker uses entries from your contact list"</string>
+ <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on keypress"</string>
+ <string name="sound_on_keypress" msgid="6093592297198243644">"Sound on keypress"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up on key press"</string>
+ <string name="general_category" msgid="1859088467017573195">"General"</string>
+ <string name="correction_category" msgid="2236750915056607613">"Text correction"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"Gesture typing"</string>
+ <string name="misc_category" msgid="6894192814868233453">"Other options"</string>
+ <string name="advanced_settings" msgid="362895144495591463">"Advanced settings"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Options for experts"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Switch to other input methods"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Language switch key also covers other input methods"</string>
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Language switch key"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Show when multiple input languages are enabled"</string>
+ <string name="sliding_key_input_preview" msgid="6604262359510068370">"Show slide indicator"</string>
+ <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Display visual cue while sliding from Shift or Symbol keys"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Key pop-up dismiss delay"</string>
+ <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"No delay"</string>
+ <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
+ <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g>ms"</string>
+ <string name="settings_system_default" msgid="6268225104743331821">"System default"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"Suggest Contact names"</string>
+ <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Use names from Contacts for suggestions and corrections"</string>
+ <string name="use_double_space_period" msgid="8781529969425082860">"Double-space full stop"</string>
+ <string name="use_double_space_period_summary" msgid="6532892187247952799">"Double tap on spacebar inserts a full stop followed by a space"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"Auto-capitalisation"</string>
+ <string name="auto_cap_summary" msgid="7934452761022946874">"Capitalise the first word of each sentence"</string>
+ <string name="edit_personal_dictionary" msgid="3996910038952940420">"Personal dictionary"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Add-on dictionaries"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Main dictionary"</string>
+ <string name="prefs_show_suggestions" msgid="8026799663445531637">"Show correction suggestions"</string>
+ <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Display suggested words while typing"</string>
+ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Always show"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Show in portrait mode"</string>
+ <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Always hide"</string>
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Block offensive words"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Do not suggest potentially offensive words"</string>
+ <string name="auto_correction" msgid="7630720885194996950">"Auto-correction"</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"Correct mistyped words automatically with spacebar and punctuation"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Off"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
+ <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Aggressive"</string>
+ <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Very aggressive"</string>
+ <string name="bigram_prediction" msgid="1084449187723948550">"Next-word suggestions"</string>
+ <string name="bigram_prediction_summary" msgid="3896362682751109677">"Use the previous word when making suggestions"</string>
+ <string name="gesture_input" msgid="826951152254563827">"Enable gesture typing"</string>
+ <string name="gesture_input_summary" msgid="9180350639305731231">"Input a word by sliding through the letters"</string>
+ <string name="gesture_preview_trail" msgid="3802333369335722221">"Show gesture trail"</string>
+ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamic floating preview"</string>
+ <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"See the suggested word while gesturing"</string>
+ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Saved"</string>
+ <string name="label_go_key" msgid="1635148082137219148">"Go"</string>
+ <string name="label_next_key" msgid="362972844525672568">"Next"</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"Prev"</string>
+ <string name="label_done_key" msgid="2441578748772529288">"Done"</string>
+ <string name="label_send_key" msgid="2815056534433717444">"Send"</string>
+ <string name="label_pause_key" msgid="181098308428035340">"Pause"</string>
+ <string name="label_wait_key" msgid="6402152600878093134">"Wait"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Plug in a headset to hear password keys spoken aloud."</string>
+ <string name="spoken_current_text_is" msgid="2485723011272583845">"Current text is %s"</string>
+ <string name="spoken_no_text_entered" msgid="7479685225597344496">"No text entered"</string>
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> corrects <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> to <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> performs auto-correction"</string>
+ <string name="spoken_description_unknown" msgid="3197434010402179157">"Key code %d"</string>
+ <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift on (tap to disable)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock on (tap to disable)"</string>
+ <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
+ <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbols"</string>
+ <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letters"</string>
+ <string name="spoken_description_to_numeric" msgid="591752092685161732">"Numbers"</string>
+ <string name="spoken_description_settings" msgid="4627462689603838099">"Settings"</string>
+ <string name="spoken_description_tab" msgid="2667716002663482248">"Tab"</string>
+ <string name="spoken_description_space" msgid="2582521050049860859">"Space"</string>
+ <string name="spoken_description_mic" msgid="615536748882611950">"Voice input"</string>
+ <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley face"</string>
+ <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Search"</string>
+ <string name="spoken_description_dot" msgid="40711082435231673">"Dot"</string>
+ <string name="spoken_description_language_switch" msgid="5507091328222331316">"Switch language"</string>
+ <string name="spoken_description_action_next" msgid="8636078276664150324">"Next"</string>
+ <string name="spoken_description_action_previous" msgid="800872415009336208">"Previous"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift enabled"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock enabled"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift disabled"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbols mode"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Letters mode"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Phone mode"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Phone symbols mode"</string>
+ <string name="announce_keyboard_hidden" msgid="8718927835531429807">"Keyboard hidden"</string>
+ <string name="announce_keyboard_mode" msgid="4729081055438508321">"Showing <xliff:g id="MODE">%s</xliff:g> keyboard"</string>
+ <string name="keyboard_mode_date" msgid="3137520166817128102">"date"</string>
+ <string name="keyboard_mode_date_time" msgid="339593358488851072">"date and time"</string>
+ <string name="keyboard_mode_email" msgid="6216248078128294262">"email"</string>
+ <string name="keyboard_mode_im" msgid="1137405089766557048">"messaging"</string>
+ <string name="keyboard_mode_number" msgid="7991623440699957069">"number"</string>
+ <string name="keyboard_mode_phone" msgid="6851627527401433229">"phone"</string>
+ <string name="keyboard_mode_text" msgid="6479436687899701619">"text"</string>
+ <string name="keyboard_mode_time" msgid="4381856885582143277">"time"</string>
+ <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string>
+ <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"On main keyboard"</string>
+ <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"On symbols keyboard"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"Off"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic on main keyboard"</string>
+ <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic on symbols keyboard"</string>
+ <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Voice input is disabled"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
+ <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
+ <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
+ <string name="select_language" msgid="3693815588777926848">"Input languages"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"Enable user feedback"</string>
+ <string name="prefs_description_log" msgid="7525225584555429211">"Help improve this input method editor by automatically sending usage statistics and crash reports"</string>
+ <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string>
+ <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"English (UK) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"English (US) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"Spanish (US) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_nepali_traditional" msgid="9032247506728040447">"<xliff:g id="LANGUAGE">%s</xliff:g> (Traditional)"</string>
+ <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>
+ <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Alphabet (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Alphabet (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alphabet (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alphabet (PC)"</string>
+ <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Customised input styles"</string>
+ <string name="add_style" msgid="6163126614514489951">"Add style"</string>
+ <string name="add" msgid="8299699805688017798">"Add"</string>
+ <string name="remove" msgid="4486081658752944606">"Remove"</string>
+ <string name="save" msgid="7646738597196767214">"Save"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Language"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Your customised input style needs to be enabled before you start using it. Do you want to enable it now?"</string>
+ <string name="enable" msgid="5031294444630523247">"Enable"</string>
+ <string name="not_now" msgid="6172462888202790482">"Not now"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"The same input style already exists: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+ <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Usability study mode"</string>
+ <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Keypress vibration duration"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Keypress sound volume"</string>
+ <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Read external dictionary file"</string>
+ <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No dictionary files in the Downloads folder"</string>
+ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Select a dictionary file to install"</string>
+ <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Really install this file for <xliff:g id="LOCALE_NAME">%s</xliff:g>?"</string>
+ <string name="error" msgid="8940763624668513648">"There was an error"</string>
+ <string name="button_default" msgid="3988017840431881491">"Default"</string>
+ <string name="setup_welcome_title" msgid="6112821709832031715">"Welcome to <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_welcome_additional_description" msgid="8150252008545768953">"with Gesture Typing"</string>
+ <string name="setup_start_action" msgid="8936036460897347708">"Get started"</string>
+ <string name="setup_next_action" msgid="371821437915144603">"Next step"</string>
+ <string name="setup_steps_title" msgid="6400373034871816182">"Setting up <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_title" msgid="3147967630253462315">"Enable <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_instruction" msgid="2578631936624637241">"Please tick \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" in your Language &amp; input settings. This will authorise it to run on your device."</string>
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> is already enabled in your Language &amp; input settings, so this step is done. On to the next one!"</string>
+ <string name="setup_step1_action" msgid="4366513534999901728">"Enable in Settings"</string>
+ <string name="setup_step2_title" msgid="6860725447906690594">"Switch to <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step2_instruction" msgid="9141481964870023336">"Next, select \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" as your active text-input method."</string>
+ <string name="setup_step2_action" msgid="1660330307159824337">"Switch input methods"</string>
+ <string name="setup_step3_title" msgid="3154757183631490281">"Congratulations, you\'re all set!"</string>
+ <string name="setup_step3_instruction" msgid="8025981829605426000">"Now you can type in all your favourite apps with <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
+ <string name="setup_step3_action" msgid="600879797256942259">"Configure additional languages"</string>
+ <string name="setup_finish_action" msgid="276559243409465389">"Finished"</string>
+ <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Show app icon"</string>
+ <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Display application icon in the launcher"</string>
+ <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
+ <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
+ <string name="dictionary_service_name" msgid="6237472350693511448">"Dictionary Service"</string>
+ <string name="download_description" msgid="6014835283119198591">"Dictionary update information"</string>
+ <string name="dictionary_settings_title" msgid="8091417676045693313">"Add-on dictionaries"</string>
+ <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dictionary available"</string>
+ <string name="dictionary_settings_summary" msgid="5305694987799824349">"Settings for dictionaries"</string>
+ <string name="user_dictionaries" msgid="3582332055892252845">"User dictionaries"</string>
+ <string name="default_user_dict_pref_name" msgid="1625055720489280530">"User dictionary"</string>
+ <string name="dictionary_available" msgid="4728975345815214218">"Dictionary available"</string>
+ <string name="dictionary_downloading" msgid="2982650524622620983">"Currently downloading"</string>
+ <string name="dictionary_installed" msgid="8081558343559342962">"Installed"</string>
+ <string name="dictionary_disabled" msgid="8950383219564621762">"Installed, disabled"</string>
+ <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Problem connecting to dictionary service"</string>
+ <string name="no_dictionaries_available" msgid="8039920716566132611">"No dictionaries available"</string>
+ <string name="check_for_updates_now" msgid="8087688440916388581">"Refresh"</string>
+ <string name="last_update" msgid="730467549913588780">"Last updated"</string>
+ <string name="message_updating" msgid="4457761393932375219">"Checking for updates"</string>
+ <string name="message_loading" msgid="8689096636874758814">"Loading..."</string>
+ <string name="main_dict_description" msgid="3072821352793492143">"Main dictionary"</string>
+ <string name="cancel" msgid="6830980399865683324">"Cancel"</string>
+ <string name="install_dict" msgid="180852772562189365">"Install"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"Cancel"</string>
+ <string name="delete_dict" msgid="756853268088330054">"Delete"</string>
+ <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"The selected language on your mobile device has an available dictionary.&lt;br/&gt; We recommend &lt;b&gt;downloading&lt;/b&gt; the <xliff:g id="LANGUAGE">%1$s</xliff:g> dictionary to improve your typing experience.&lt;br/&gt; &lt;br/&gt; The download could take a minute or two over 3G. Charges may apply if you don\'t have an &lt;b&gt;unlimited data plan&lt;/b&gt;.&lt;br/&gt; If you are not sure which data plan you have, we recommend finding a Wi-Fi connection to start the download automatically.&lt;br/&gt; &lt;br/&gt; Tip: You can download and remove dictionaries by going to &lt;b&gt;Language &amp; input&lt;/b&gt; in the &lt;b&gt;Settings&lt;/b&gt; menu of your mobile device."</string>
+ <string name="download_over_metered" msgid="1643065851159409546">"Download now (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+ <string name="do_not_download_over_metered" msgid="2176209579313941583">"Download over Wi-Fi"</string>
+ <string name="dict_available_notification_title" msgid="6514288591959117288">"A dictionary is available for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+ <string name="dict_available_notification_description" msgid="1075194169443163487">"Press to review and download"</string>
+ <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Downloading: suggestions for <xliff:g id="LANGUAGE">%1$s</xliff:g> will be ready soon."</string>
+ <string name="version_text" msgid="2715354215568469385">"Version <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Add"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Add to dictionary"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Phrase"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"More options"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Fewer options"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"OK"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Word:"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Shortcut:"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Language:"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Type a word"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Optional shortcut"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Edit word"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Edit"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Delete"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"You don\'t have any words in the user dictionary. Add a word by touching the Add (+) button."</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"For all languages"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"More languages…"</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"Delete"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+</resources>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 42c3932f6..2d7872aaa 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Enchufa tus auriculares para escuchar en voz alta qué teclas presionas al ingresar una contraseña."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"El texto actual es %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"No se ingresó texto."</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"La tecla <xliff:g id="KEY">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> por <xliff:g id="CORRECTED">%3$s</xliff:g>."</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"La tecla <xliff:g id="KEY">%1$s</xliff:g> corrige automáticamente."</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Clave de código %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Mayús"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Se activó el modo Mayúscula (toca para desactivarlo)."</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index 4d72799f4..4dfc57fa6 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -62,7 +62,7 @@
<string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"No sugerir palabras potencialmente ofensivas"</string>
<string name="auto_correction" msgid="7630720885194996950">"Autocorrección"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Pulsar la tecla de espacio o punto para corregir errores"</string>
- <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desactivada"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"No"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Parcial"</string>
<string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Total"</string>
<string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Casi total"</string>
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Conecta un auricular para escuchar las contraseñas en voz alta."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"El texto actual es %s."</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"No se ha introducido texto."</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"La tecla <xliff:g id="KEY">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> a <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"La tecla <xliff:g id="KEY">%1$s</xliff:g> corrige automáticamente"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Código del teclado: %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Mayús"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Mayúsculas activadas (tocar para inhabilitar)"</string>
@@ -128,7 +126,7 @@
<string name="voice_input" msgid="3583258583521397548">"Tecla de entrada de voz"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"En teclado principal"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"En teclado de símbolos"</string>
- <string name="voice_input_modes_off" msgid="3745699748218082014">"Desactivada"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"No"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en teclado principal"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrófono en teclado de símbolos"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entrada de voz inhabilitada"</string>
diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml
index 5706fa105..3a27a8892 100644
--- a/java/res/values-et-rEE/strings.xml
+++ b/java/res/values-et-rEE/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Ühendage peakomplekt, et kuulata paroole."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Praegune tekst on %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Teksti ei ole sisestatud"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Klahvi <xliff:g id="KEY">%1$s</xliff:g> vajutamisel parandatakse sõna <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> sõnaks <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Klahvi <xliff:g id="KEY">%1$s</xliff:g> vajutamisel tehakse automaatne parandus"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Klahvi kood: %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Tõstuklahv"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Tõstuklahv sees (puudutage keelamiseks)"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index c03e440e4..a6d9bbafd 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -86,10 +86,8 @@
<!-- no translation found for spoken_current_text_is (2485723011272583845) -->
<skip />
<string name="spoken_no_text_entered" msgid="7479685225597344496">"متنی وارد نشده است"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g>، ‏<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> را به <xliff:g id="CORRECTED">%3$s</xliff:g> تصحیح می‌کند"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> تصحیح خودکار را انجام می‌دهد"</string>
<!-- String.format failed for translation -->
<!-- no translation found for spoken_description_unknown (3197434010402179157) -->
<skip />
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 744e60420..cee1b7d24 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Liitä kuulokkeet, niin kuulet mitä näppäimiä painat kirjoittaessasi salasanaa."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Nykyinen teksti on %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Ei kirjoitettua tekstiä"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> korjaa sanan <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> sanaksi <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> suorittaa automaattisen korjauksen"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Näppäimen koodi %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Vaihto"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Vaihto päällä (poista käytöstä napauttamalla)"</string>
diff --git a/java/res/values-fr-rCA/strings-appname.xml b/java/res/values-fr-rCA/strings-appname.xml
new file mode 100644
index 000000000..d45e239a0
--- /dev/null
+++ b/java/res/values-fr-rCA/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"Clavier Android (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"Correcteur orthographique Android (AOSP)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"Paramètres du clavier Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"Paramètres du correcteur orthographique Android (AOSP)"</string>
+</resources>
diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml
index b56463ed9..6f33539ce 100644
--- a/java/res/values-fr-rCA/strings.xml
+++ b/java/res/values-fr-rCA/strings.xml
@@ -1,19 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="english_ime_name" msgid="7252517407088836577">"Clavier Android"</string>
+ <string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Commandes journaux rech."</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Rechercher noms contacts"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Correcteur orthographique utilise entrées de liste de contacts."</string>
+ <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string>
+ <string name="sound_on_keypress" msgid="6093592297198243644">"Son à chaque touche"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"Agrandir les caractères"</string>
+ <string name="general_category" msgid="1859088467017573195">"Général"</string>
+ <string name="correction_category" msgid="2236750915056607613">"Correction du texte"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"Saisie gestuelle"</string>
+ <string name="misc_category" msgid="6894192814868233453">"Autres options"</string>
+ <string name="advanced_settings" msgid="362895144495591463">"Paramètres avancés"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Options destinées aux experts"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Autres modes de saisie"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La touche de sélection de langue couvre d\'autres modes de saisie"</string>
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Touche de sélection de langue"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Afficher lorsque plusieurs langues de saisie sont activées"</string>
+ <string name="sliding_key_input_preview" msgid="6604262359510068370">"Aff. indicateur saisie gestuelle"</string>
+ <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Aff. un repère visuel si l\'utilisateur appuie sur Maj ou Symboles"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Masquer touche agrandie"</string>
+ <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Aucun délai"</string>
+ <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string>
+ <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> ms"</string>
+ <string name="settings_system_default" msgid="6268225104743331821">"Paramètres par défaut"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"Proposer noms de contacts"</string>
+ <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utiliser des noms de contacts pour les suggestions et corrections"</string>
+ <string name="use_double_space_period" msgid="8781529969425082860">"Point et espace"</string>
+ <string name="use_double_space_period_summary" msgid="6532892187247952799">"Appuyez deux fois sur la barre d\'espace pour insérer un point et une espace"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"Majuscules automatiques"</string>
+ <string name="auto_cap_summary" msgid="7934452761022946874">"Majuscule au premier mot de chaque phrase"</string>
+ <string name="edit_personal_dictionary" msgid="3996910038952940420">"Dictionnaire personnel"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Dictionnaires complémentaires"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Dictionnaire principal"</string>
+ <string name="prefs_show_suggestions" msgid="8026799663445531637">"Suggestions de correction"</string>
+ <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Afficher les suggestions de terme lors de la saisie"</string>
+ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Toujours afficher"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Afficher en mode Portrait"</string>
+ <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Toujours masquer"</string>
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquer les termes choquants"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Pas de termes potentiellement choquants"</string>
+ <string name="auto_correction" msgid="7630720885194996950">"Correction auto"</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"Corriger autom. orthographe (pression sur barre espace/signes ponctuation)"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Désactiver"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Simple"</string>
+ <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Proactive"</string>
+ <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Très exigeante"</string>
+ <string name="bigram_prediction" msgid="1084449187723948550">"Suggestions pour le mot suivant"</string>
+ <string name="bigram_prediction_summary" msgid="3896362682751109677">"Utiliser le mot précédent pour les suggestions"</string>
+ <string name="gesture_input" msgid="826951152254563827">"Activer la saisie gestuelle"</string>
+ <string name="gesture_input_summary" msgid="9180350639305731231">"Saisir un mot en faisant glisser le doigt sur les lettres"</string>
+ <string name="gesture_preview_trail" msgid="3802333369335722221">"Afficher le tracé du geste"</string>
+ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Aperçu flottant dynamique"</string>
+ <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Afficher le mot suggéré lors des gestes"</string>
+ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : enregistré"</string>
+ <string name="label_go_key" msgid="1635148082137219148">"Aller"</string>
+ <string name="label_next_key" msgid="362972844525672568">"Suivant"</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"Préc."</string>
+ <string name="label_done_key" msgid="2441578748772529288">"Terminé"</string>
+ <string name="label_send_key" msgid="2815056534433717444">"Envoyer"</string>
+ <string name="label_pause_key" msgid="181098308428035340">"Suspendre"</string>
+ <string name="label_wait_key" msgid="6402152600878093134">"Attendre"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Branchez des écouteurs pour entendre l\'énoncé à haute voix des touches lors de la saisie du mot de passe."</string>
+ <string name="spoken_current_text_is" msgid="2485723011272583845">"Le texte actuel est %s"</string>
+ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Aucun texte saisi"</string>
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"La touche <xliff:g id="KEY">%1$s</xliff:g> permet de corriger « <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> » par « <xliff:g id="CORRECTED">%3$s</xliff:g> »"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"La touche <xliff:g id="KEY">%1$s</xliff:g> permet d\'activer la correction automatique"</string>
+ <string name="spoken_description_unknown" msgid="3197434010402179157">"Code touche %d"</string>
+ <string name="spoken_description_shift" msgid="244197883292549308">"Maj"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Touche Maj activée (appuyer pour désactiver)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Verrouillage des majuscules activé (appuyer pour désactiver)"</string>
+ <string name="spoken_description_delete" msgid="8740376944276199801">"Supprimer"</string>
+ <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboles"</string>
+ <string name="spoken_description_to_alpha" msgid="23129338819771807">"Lettres"</string>
+ <string name="spoken_description_to_numeric" msgid="591752092685161732">"Nombres"</string>
+ <string name="spoken_description_settings" msgid="4627462689603838099">"Paramètres"</string>
+ <string name="spoken_description_tab" msgid="2667716002663482248">"Onglet"</string>
+ <string name="spoken_description_space" msgid="2582521050049860859">"Espace"</string>
+ <string name="spoken_description_mic" msgid="615536748882611950">"Saisie vocale"</string>
+ <string name="spoken_description_smiley" msgid="2256309826200113918">"Émoticône"</string>
+ <string name="spoken_description_return" msgid="8178083177238315647">"Renvoyer"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Rechercher"</string>
+ <string name="spoken_description_dot" msgid="40711082435231673">"Point"</string>
+ <string name="spoken_description_language_switch" msgid="5507091328222331316">"Changer de langue"</string>
+ <string name="spoken_description_action_next" msgid="8636078276664150324">"Suivant"</string>
+ <string name="spoken_description_action_previous" msgid="800872415009336208">"Précédent"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Touche Maj activée"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Verrouillage des majuscules activé"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Touche Maj désactivée"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode Symboles"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode Lettres"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode Téléphone"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode Symboles du téléphone"</string>
+ <string name="announce_keyboard_hidden" msgid="8718927835531429807">"Clavier masqué"</string>
+ <string name="announce_keyboard_mode" msgid="4729081055438508321">"Affichage du clavier <xliff:g id="MODE">%s</xliff:g>"</string>
+ <string name="keyboard_mode_date" msgid="3137520166817128102">"Date"</string>
+ <string name="keyboard_mode_date_time" msgid="339593358488851072">"Date et heure"</string>
+ <string name="keyboard_mode_email" msgid="6216248078128294262">"Courriel"</string>
+ <string name="keyboard_mode_im" msgid="1137405089766557048">"SMS/MMS"</string>
+ <string name="keyboard_mode_number" msgid="7991623440699957069">"Nombre"</string>
+ <string name="keyboard_mode_phone" msgid="6851627527401433229">"Numéro de téléphone"</string>
+ <string name="keyboard_mode_text" msgid="6479436687899701619">"Texte"</string>
+ <string name="keyboard_mode_time" msgid="4381856885582143277">"Heure"</string>
+ <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Touche de saisie vocale"</string>
+ <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sur le clavier principal"</string>
+ <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sur clavier symboles"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"Désactiver"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micro sur le clavier principal"</string>
+ <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro sur le clavier des symboles"</string>
+ <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Saisie vocale désactivée"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string>
+ <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string>
+ <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string>
+ <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"Autoriser les commentaires des utilisateurs"</string>
+ <string name="prefs_description_log" msgid="7525225584555429211">"Contribuer à l\'amélioration de cet éditeur du mode de saisie grâce à l\'envoi automatique de statistiques d\'utilisation et de rapports d\'erreur"</string>
+ <string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (britannique)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (États-Unis)"</string>
+ <string name="subtype_es_US" msgid="5583145191430180200">"Espagnol (États-Unis)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Anglais (Royaume-Uni) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Anglais (États-Unis) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"Espagnol, États-Unis (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_nepali_traditional" msgid="9032247506728040447">"<xliff:g id="LANGUAGE">%s</xliff:g> (traditionnel)"</string>
+ <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>
+ <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Alphabet latin (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Alphabet latin (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alphabet latin (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alphabet latin (PC)"</string>
+ <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Styles saisie personnalisés"</string>
+ <string name="add_style" msgid="6163126614514489951">"Ajouter style"</string>
+ <string name="add" msgid="8299699805688017798">"Ajouter"</string>
+ <string name="remove" msgid="4486081658752944606">"Supprimer"</string>
+ <string name="save" msgid="7646738597196767214">"Enregistrer"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Langue"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Disposition"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Vous devez activer votre style de saisie personnalisé avant de l\'utiliser. Voulez-vous le faire maintenant ?"</string>
+ <string name="enable" msgid="5031294444630523247">"Activer"</string>
+ <string name="not_now" msgid="6172462888202790482">"Pas maintenant"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Le style de saisie suivant existe déjà : <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
+ <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'étude de l\'utilisabilité"</string>
+ <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Délai appui prolongé sur touche"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Durée vibration press. touche"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume pression de touche"</string>
+ <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lire un fichier de dictionnaire externe"</string>
+ <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Aucun fichier de dictionnaire dans le dossier \"Téléchargements\""</string>
+ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Sélectionner un fichier de dictionnaire à installer"</string>
+ <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Installer ce fichier pour la langue \"<xliff:g id="LOCALE_NAME">%s</xliff:g>\" ?"</string>
+ <string name="error" msgid="8940763624668513648">"Une erreur s\'est produite"</string>
+ <string name="button_default" msgid="3988017840431881491">"Par défaut"</string>
+ <string name="setup_welcome_title" msgid="6112821709832031715">"Bienvenue dans <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_welcome_additional_description" msgid="8150252008545768953">"avec la saisie gestuelle"</string>
+ <string name="setup_start_action" msgid="8936036460897347708">"Commencer"</string>
+ <string name="setup_next_action" msgid="371821437915144603">"Étape suivante"</string>
+ <string name="setup_steps_title" msgid="6400373034871816182">"Configurer <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_title" msgid="3147967630253462315">"Activer <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_instruction" msgid="2578631936624637241">"Sous \"Langue et saisie\", cochez \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" pour autoriser son exécution sur l\'appareil."</string>
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"L\'application \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" est déjà activée dans vos paramètres \"Langue et saisie\". Passez à l\'étape suivante."</string>
+ <string name="setup_step1_action" msgid="4366513534999901728">"Activer le clavier dans les paramètres"</string>
+ <string name="setup_step2_title" msgid="6860725447906690594">"Basculer vers <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step2_instruction" msgid="9141481964870023336">"Sélectionnez ensuite \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" comme mode de saisie actif."</string>
+ <string name="setup_step2_action" msgid="1660330307159824337">"Changer de mode de saisie"</string>
+ <string name="setup_step3_title" msgid="3154757183631490281">"Félicitations, l\'opération est terminée"</string>
+ <string name="setup_step3_instruction" msgid="8025981829605426000">"Avec <xliff:g id="APPLICATION_NAME">%s</xliff:g>, vous pouvez saisir du texte dans toutes vos applications préférées."</string>
+ <string name="setup_step3_action" msgid="600879797256942259">"Configurer des langues supplémentaires"</string>
+ <string name="setup_finish_action" msgid="276559243409465389">"OK"</string>
+ <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Afficher icône application"</string>
+ <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Afficher l\'icône de l\'application dans le lanceur"</string>
+ <string name="app_name" msgid="6320102637491234792">"Fournisseur de dictionnaires"</string>
+ <string name="dictionary_provider_name" msgid="3027315045397363079">"Fournisseur de dictionnaires"</string>
+ <string name="dictionary_service_name" msgid="6237472350693511448">"Service de dictionnaires"</string>
+ <string name="download_description" msgid="6014835283119198591">"Informations relatives à la mise à jour des dictionnaires"</string>
+ <string name="dictionary_settings_title" msgid="8091417676045693313">"Dictionnaires complémentaires"</string>
+ <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dictionnaire disponible"</string>
+ <string name="dictionary_settings_summary" msgid="5305694987799824349">"Paramètres des dictionnaires"</string>
+ <string name="user_dictionaries" msgid="3582332055892252845">"Dictionnaires personnels"</string>
+ <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Dictionnaire personnel"</string>
+ <string name="dictionary_available" msgid="4728975345815214218">"Dictionnaire disponible"</string>
+ <string name="dictionary_downloading" msgid="2982650524622620983">"Téléchargement en cours…"</string>
+ <string name="dictionary_installed" msgid="8081558343559342962">"Installé"</string>
+ <string name="dictionary_disabled" msgid="8950383219564621762">"Installé, désactivé"</string>
+ <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Pas de service dico."</string>
+ <string name="no_dictionaries_available" msgid="8039920716566132611">"Aucun dictionnaire"</string>
+ <string name="check_for_updates_now" msgid="8087688440916388581">"Actualiser"</string>
+ <string name="last_update" msgid="730467549913588780">"Dernière mise à jour"</string>
+ <string name="message_updating" msgid="4457761393932375219">"Recherche de mises à jour en cours…"</string>
+ <string name="message_loading" msgid="8689096636874758814">"Chargement en cours..."</string>
+ <string name="main_dict_description" msgid="3072821352793492143">"Dictionnaire principal"</string>
+ <string name="cancel" msgid="6830980399865683324">"Annuler"</string>
+ <string name="install_dict" msgid="180852772562189365">"Installer"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"Annuler"</string>
+ <string name="delete_dict" msgid="756853268088330054">"Supprimer"</string>
+ <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Un dictionnaire est disponible pour la langue sélectionnée sur votre appareil mobile.&lt;br/&gt; Nous vous invitons à &lt;b&gt;télécharger&lt;/b&gt; le dictionnaire <xliff:g id="LANGUAGE">%1$s</xliff:g> pour faciliter votre saisie.&lt;br/&gt; &lt;br/&gt; Le téléchargement peut prendre une à deux minutes via une connexion 3G. Des frais peuvent s\'appliquer si vous ne disposez pas d\'un &lt;b&gt;forfait Internet illimité&lt;/b&gt;.&lt;br/&gt; Si vous n\'êtes pas sûr de votre forfait, nous vous conseillons d\'utiliser une connexion Wi-Fi pour lancer automatiquement le téléchargement.&lt;br/&gt; &lt;br/&gt; Astuce : Vous pouvez télécharger et supprimer des dictionnaires dans la section &lt;b&gt;Langue et saisie&lt;/b&gt; du menu &lt;b&gt;Paramètres&lt;/b&gt; de votre appareil mobile."</string>
+ <string name="download_over_metered" msgid="1643065851159409546">"Télécharger (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> Mo)"</string>
+ <string name="do_not_download_over_metered" msgid="2176209579313941583">"Télécharger via Wi-Fi"</string>
+ <string name="dict_available_notification_title" msgid="6514288591959117288">"Un dictionnaire est disponible en <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+ <string name="dict_available_notification_description" msgid="1075194169443163487">"Appuyez ici pour consulter et télécharger le dictionnaire."</string>
+ <string name="toast_downloading_suggestions" msgid="1313027353588566660">"En cours de téléchargement. Des suggestions pour la langue suivante seront bientôt disponibles : <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
+ <string name="version_text" msgid="2715354215568469385">"Version <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Ajouter"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Ajouter au dictionnaire"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Expression"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Plus d\'options"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Moins d\'options"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"OK"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Mot :"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Raccourci :"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Langue :"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Saisissez un mot"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Raccourci facultatif"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Modifier le mot"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Modifier"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Supprimer"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Votre dictionnaire personnel ne contient aucun mot. Ajoutez un mot en appuyant sur le bouton d\'ajout (\"+\")."</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Pour toutes les langues"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Plus de langues…"</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"Supprimer"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
</resources>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 5fedd4ebd..b850df94f 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Branchez des écouteurs pour entendre l\'énoncé à haute voix des touches lors de la saisie du mot de passe."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Le texte actuel est %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Aucun texte saisi"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"La touche <xliff:g id="KEY">%1$s</xliff:g> permet de remplacer \"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>\" par \"<xliff:g id="CORRECTED">%3$s</xliff:g>\"."</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"La touche <xliff:g id="KEY">%1$s</xliff:g> permet d\'activer la correction automatique."</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Code touche %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Maj"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Touche Maj activée (appuyer pour désactiver)"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 3b3228a9f..6d2d5d2fe 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"ज़ोर से बोली गई पासवर्ड कुंजियां सुनने के लिए हेडसेट प्‍लग इन करें."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"वर्तमान पाठ %s है"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"कोई पाठ दर्ज नहीं किया गया"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> को सुधार कर <xliff:g id="CORRECTED">%3$s</xliff:g> करता है"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> स्वत: सुधार करता है"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"कुंजी कोड %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"शिफ़्ट"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift चालू (अक्षम करने के लिए टैप करें)"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index caef9541d..ee2e68a1f 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Priključite slušalice da biste čuli tipke zaporke izgovorene naglas."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Trenutačni tekst je %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nije unesen tekst"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> ispravlja <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> u <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> vrši samoispravljanje"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Kôd tipke %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Uključena tipka Shift (dotaknite da onemogućite)"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 3b0ee4798..71fce941e 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Csatlakoztasson egy headsetet, ha hallani szeretné a jelszót felolvasva."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"A jelenlegi szöveg: %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Szöveg nincs megadva"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> billentyű: <xliff:g id="CORRECTED">%3$s</xliff:g> szóra javítja a következőt: <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> billentyű automatikus javítást végez"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Billentyűkód: %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift be van kapcsolva (érintse meg a kikapcsoláshoz)"</string>
diff --git a/java/res/values-hy-rAM/strings-appname.xml b/java/res/values-hy-rAM/strings-appname.xml
new file mode 100644
index 000000000..dc3c0c678
--- /dev/null
+++ b/java/res/values-hy-rAM/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"Android Ստեղնաշար (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"Android տառասխալների ուղղիչ (AOSP)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"Android ստեղնաշարի կարգավորումներ (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"Android տառասխալների ուղղիչի կարգավորումներ (AOSP)"</string>
+</resources>
diff --git a/java/res/values-hy-rAM/strings.xml b/java/res/values-hy-rAM/strings.xml
new file mode 100644
index 000000000..b7ca149dd
--- /dev/null
+++ b/java/res/values-hy-rAM/strings.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_input_options" msgid="3909945612939668554">"Ներածման ընտրանքներ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Հետազոտական գրառումների հրամաններ"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Փնտրել կոնտակտային անուններ"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Տառասխալների ուղղիչն օգտագործում է ձեր կոնտակտների ցանկի տվյալները"</string>
+ <string name="vibrate_on_keypress" msgid="5258079494276955460">"Թրթռալ սեղմման ժամանակ"</string>
+ <string name="sound_on_keypress" msgid="6093592297198243644">"Ձայնը սեղմման ժամանակ"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"Ելնող պատուհան՝ ստեղնի հպման դեպքում"</string>
+ <string name="general_category" msgid="1859088467017573195">"Ընդհանուր"</string>
+ <string name="correction_category" msgid="2236750915056607613">"Տեքստի ուղղում"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"Ժեստերով մուտքագրում"</string>
+ <string name="misc_category" msgid="6894192814868233453">"Այլ ընտրանքներ"</string>
+ <string name="advanced_settings" msgid="362895144495591463">"Ընդլայնված կարգավորումներ"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"Ընտրանքներ փորձագետների համար"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Անցնել մուտքագրման այլ եղանակների"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Լեզվի փոխարկման բանալին ընդգրկում է այլ մուտքագրման եղանակներ ևս"</string>
+ <string name="show_language_switch_key" msgid="5915478828318774384">"Լեզվի փոխարկման ստեղն"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Ցույց տալ, երբ մուտքագրման մի քանի լեզուներ են միացված"</string>
+ <string name="sliding_key_input_preview" msgid="6604262359510068370">"Ցուցադրել սահքի ցուցիչը"</string>
+ <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Ցուցադրել տեսողական հուշումը Shift-ի կամ նշանների ստեղներից սահեցման ընթացքում"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ելնող պատուհանի հեռացման հետաձգման ստեղն"</string>
+ <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Առանց հետաձգման"</string>
+ <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Նախնականը"</string>
+ <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g>մվ"</string>
+ <string name="settings_system_default" msgid="6268225104743331821">"Համակարգի լռելյայնները"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"Առաջարկել կոնտակտների անունները"</string>
+ <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Օգտագործել կոնտակտների անունները՝ առաջարկների և ուղղումների համար"</string>
+ <string name="use_double_space_period" msgid="8781529969425082860">"Կրկնաբացակի վերջակետ"</string>
+ <string name="use_double_space_period_summary" msgid="6532892187247952799">"Բացակի ստեղնի կրկնակի հպումը բացակից հետո վերջակետ է դնում"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"Ավտոմատ գլխատառացում"</string>
+ <string name="auto_cap_summary" msgid="7934452761022946874">"Գլխատառել յուրաքանչյուր նախադասության առաջին բառը"</string>
+ <string name="edit_personal_dictionary" msgid="3996910038952940420">"Անհատական բառարան"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"Ավելացնել բառարաններ"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"Հիմնական բառարան"</string>
+ <string name="prefs_show_suggestions" msgid="8026799663445531637">"Ցուցադրել ուղղումների առաջարկներ"</string>
+ <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Ցուցադրել առաջարկվող բառերը մուտքագրման ընթացքում"</string>
+ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Միշտ ցուցադրել"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Ցուցադրել դիմանկարային ռեժիմում"</string>
+ <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Միշտ թաքցնել"</string>
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Արգելափակել վիրավորական բառերը"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Չառաջարկել հավանական վիրավորական բառերը"</string>
+ <string name="auto_correction" msgid="7630720885194996950">"Ինքնուղղում"</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"Տպագրական սխալով բառերում ավտոմատ տեղադրել բացակներն ու կետադրական նշանները"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Անջատված"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Համեստ"</string>
+ <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Ագրեսիվ"</string>
+ <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Շատ ագրեսիվ"</string>
+ <string name="bigram_prediction" msgid="1084449187723948550">"Հաջորդ բառի առաջարկներ"</string>
+ <string name="bigram_prediction_summary" msgid="3896362682751109677">"Առաջարկներ կազմելու համար օգտագործել նախորդ բառը"</string>
+ <string name="gesture_input" msgid="826951152254563827">"Միացնել ժեստերով մուտքագրումը"</string>
+ <string name="gesture_input_summary" msgid="9180350639305731231">"Մուտքագրեք բառ` սահեցնելով տառերը"</string>
+ <string name="gesture_preview_trail" msgid="3802333369335722221">"Ցույց տալ ժեստի հետագիծը"</string>
+ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Դինամիկ սահող նախատեսք"</string>
+ <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Տեսեք առաջարկված բառը՝ ժեստի միջոցով"</string>
+ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>` պահված է"</string>
+ <string name="label_go_key" msgid="1635148082137219148">"Առաջ"</string>
+ <string name="label_next_key" msgid="362972844525672568">"Հաջորդը"</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"Նխրդ"</string>
+ <string name="label_done_key" msgid="2441578748772529288">"Կատարված է"</string>
+ <string name="label_send_key" msgid="2815056534433717444">"Ուղարկել"</string>
+ <string name="label_pause_key" msgid="181098308428035340">"Դադար"</string>
+ <string name="label_wait_key" msgid="6402152600878093134">"Սպասել"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"Միացրեք ականջակալը՝ բարձրաձայն արտասանվող գաղտնաբառը լսելու համար:"</string>
+ <string name="spoken_current_text_is" msgid="2485723011272583845">"Տվյալ տեքստը %s է"</string>
+ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Տեքստ չի մուտքագրվել"</string>
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g>-ը շտկում է <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>-ը և դարձնում <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> ստեղնը ինքնաշտկում է կատարում"</string>
+ <string name="spoken_description_unknown" msgid="3197434010402179157">"Բանալու կոդը՝ %d"</string>
+ <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift-ը միացված է (հպել անջատելու համար)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock-ը միացված է (հպել՝ անջատելու համար)"</string>
+ <string name="spoken_description_delete" msgid="8740376944276199801">"Ջնջել"</string>
+ <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Նշաններ"</string>
+ <string name="spoken_description_to_alpha" msgid="23129338819771807">"Տառեր"</string>
+ <string name="spoken_description_to_numeric" msgid="591752092685161732">"Թվեր"</string>
+ <string name="spoken_description_settings" msgid="4627462689603838099">"Կարգավորումներ"</string>
+ <string name="spoken_description_tab" msgid="2667716002663482248">"Tab"</string>
+ <string name="spoken_description_space" msgid="2582521050049860859">"Բացակ"</string>
+ <string name="spoken_description_mic" msgid="615536748882611950">"Ձայնային մուտքագրում"</string>
+ <string name="spoken_description_smiley" msgid="2256309826200113918">"Ժպիտ"</string>
+ <string name="spoken_description_return" msgid="8178083177238315647">"Վերադարձ"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"Որոնել"</string>
+ <string name="spoken_description_dot" msgid="40711082435231673">"Կետ"</string>
+ <string name="spoken_description_language_switch" msgid="5507091328222331316">"Փոխել լեզուն"</string>
+ <string name="spoken_description_action_next" msgid="8636078276664150324">"Հաջորդը"</string>
+ <string name="spoken_description_action_previous" msgid="800872415009336208">"Նախորդը"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift-ը միացված է"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock-ը միացված է"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift-ն անջատված է"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Նշանների ռեժիմ"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Տառերի ռեժիմ"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Հեռախոսային ռեժիմ"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Հեռախոսի նշանների ռեժիմ"</string>
+ <string name="announce_keyboard_hidden" msgid="8718927835531429807">"Ստեղնաշարը թաքցված է"</string>
+ <string name="announce_keyboard_mode" msgid="4729081055438508321">"Ցուցադրված է <xliff:g id="MODE">%s</xliff:g> ստեղնաշարը"</string>
+ <string name="keyboard_mode_date" msgid="3137520166817128102">"ամսաթիվ"</string>
+ <string name="keyboard_mode_date_time" msgid="339593358488851072">"ամսաթիվ և ժամ"</string>
+ <string name="keyboard_mode_email" msgid="6216248078128294262">"էլփոստ"</string>
+ <string name="keyboard_mode_im" msgid="1137405089766557048">"նամակագրություն"</string>
+ <string name="keyboard_mode_number" msgid="7991623440699957069">"թվեր"</string>
+ <string name="keyboard_mode_phone" msgid="6851627527401433229">"հեռախոսահամար"</string>
+ <string name="keyboard_mode_text" msgid="6479436687899701619">"տեքստ"</string>
+ <string name="keyboard_mode_time" msgid="4381856885582143277">"ժամանակ"</string>
+ <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string>
+ <string name="voice_input" msgid="3583258583521397548">"Ձայնային մուտքագրման ստեղն"</string>
+ <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Հիմնական ստեղնաշարի վրա"</string>
+ <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Նշանների ստեղնաշարի վրա"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"Անջատված"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Բարձրախոս հիմնական ստեղնաշարի վրա"</string>
+ <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Բարձրախոս նշանների ստեղնաշարի վրա"</string>
+ <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Ձայնային մուտքագրումն անջատված է"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"Կարգավորել մուտքագրման մեթոդները"</string>
+ <string name="language_selection_title" msgid="1651299598555326750">"Մուտքագրման լեզուներ"</string>
+ <string name="send_feedback" msgid="1780431884109392046">"Արձագանքել"</string>
+ <string name="select_language" msgid="3693815588777926848">"Մուտքագրման լեզուներ"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"Պահպանելու համար կրկին հպեք"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"Բառարանն առկա է"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"Միացնել օգտվողի արձագանքը"</string>
+ <string name="prefs_description_log" msgid="7525225584555429211">"Օգնել բարելավել այս մուտքագրման եղանակի խմբագրիչը՝ ինքնուրույն ուղարկելով Google-ին օգտագործման վիճակագրությունն ու վթարների հաշվետվությունները:"</string>
+ <string name="keyboard_layout" msgid="8451164783510487501">"Ստեղնաշարի թեման"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"Անգլերեն (ՄԹ)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"Անգլերեն (ԱՄՆ)"</string>
+ <string name="subtype_es_US" msgid="5583145191430180200">"Իսպաներեն (ԱՄՆ)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"Անգլերեն (ՄԹ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"Անգլերեն (ԱՄՆ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"Իսպաներեն (ԱՄՆ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_nepali_traditional" msgid="9032247506728040447">"<xliff:g id="LANGUAGE">%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>
+ <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Այբուբեն (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Այբուբեն (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Այբուբեն (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Այբուբեն (PC)"</string>
+ <string name="subtype_emoji" msgid="7483586578074549196">"Զմայլիկներ"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"Մուտքագրման հատուկ ոճեր"</string>
+ <string name="add_style" msgid="6163126614514489951">"Ավելացնել ոճ"</string>
+ <string name="add" msgid="8299699805688017798">"Ավելացնել"</string>
+ <string name="remove" msgid="4486081658752944606">"Հեռացնել"</string>
+ <string name="save" msgid="7646738597196767214">"Պահել"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"Lեզու"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"Դասավորություն"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"Մուտքագրման ձեր հատուկ ոճը պետք է միացված լինի նախքան դուք կսկսեք օգտագործել այն: Ցանկանո՞ւմ եք միացնել այն հիմա:"</string>
+ <string name="enable" msgid="5031294444630523247">"Միացնել"</string>
+ <string name="not_now" msgid="6172462888202790482">"Ոչ հիմա"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Մուտքագրման այսպիսի ոճ արդեն գոյություն ունի՝ <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+ <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Հարմարավետության ուսումնասիրության ռեժիմ"</string>
+ <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ստեղնի երկար սեղմման ուշացում"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Սեղմման թրթռոցի տևողություն"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Սեղմման ձայնի բարձրությունը"</string>
+ <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Կարդալ արտաքին բառարանի ֆայլը"</string>
+ <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Ներբեռնումների թղթապանակում բառարանային ֆայլեր չկան"</string>
+ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Ընտրեք բառարանային ֆայլը տեղադրման համար"</string>
+ <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"Իրո՞ք ուզում եք տեղադրել այս ֆայլը <xliff:g id="LOCALE_NAME">%s</xliff:g>-ում:"</string>
+ <string name="error" msgid="8940763624668513648">"Տեղի է ունեցել սխալ"</string>
+ <string name="button_default" msgid="3988017840431881491">"Լռելյայնը"</string>
+ <string name="setup_welcome_title" msgid="6112821709832031715">"Բարի գալուստ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_welcome_additional_description" msgid="8150252008545768953">"Ժեստային մուտքագրմամբ"</string>
+ <string name="setup_start_action" msgid="8936036460897347708">"Սկսել"</string>
+ <string name="setup_next_action" msgid="371821437915144603">"Հաջորդ քայլը"</string>
+ <string name="setup_steps_title" msgid="6400373034871816182">"Տեղադրվում է <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ը"</string>
+ <string name="setup_step1_title" msgid="3147967630253462315">"Միացնել <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ը"</string>
+ <string name="setup_step1_instruction" msgid="2578631936624637241">"Խնդրում ենք ստուգել «<xliff:g id="APPLICATION_NAME">%s</xliff:g>»-ը ձեր Լեզվի &amp; մուտքագրման կարգավորումներում: Դա կլիազորի նրան գործարկվել ձեր սարքում:"</string>
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-ն արդեն միացված է ձեր Լեզվի &amp; մուտքագրման կարգավորումներում, ուստի այս քայլն արված է: Անցնել հաջորդին:"</string>
+ <string name="setup_step1_action" msgid="4366513534999901728">"Միացնել կարգավորումներից"</string>
+ <string name="setup_step2_title" msgid="6860725447906690594">"Փոխարկել <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ին"</string>
+ <string name="setup_step2_instruction" msgid="9141481964870023336">"Հաջորդիվ, ընտրեք «<xliff:g id="APPLICATION_NAME">%s</xliff:g>»-ը որպես ձեր ակտիվ տեքստային մուտքագրման եղանակ:"</string>
+ <string name="setup_step2_action" msgid="1660330307159824337">"Փոխարկել մուտքագրման եղանակները"</string>
+ <string name="setup_step3_title" msgid="3154757183631490281">"Շնորհավորում ենք, դուք տեղադրեցիք բոլորը:"</string>
+ <string name="setup_step3_instruction" msgid="8025981829605426000">"Այժմ դուք կարող եք մուտքագրել ձեր բոլոր սիրելի հավելվածներում <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ով:"</string>
+ <string name="setup_step3_action" msgid="600879797256942259">"Կարգավորել լրացուցիչ լեզուները"</string>
+ <string name="setup_finish_action" msgid="276559243409465389">"Ավարտված"</string>
+ <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Ցույց տալ հավելվածի պատկերակը"</string>
+ <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Ցուցադրել հավելվածի պատկերակը թողարկչում"</string>
+ <string name="app_name" msgid="6320102637491234792">"Բառարանի մատակարար"</string>
+ <string name="dictionary_provider_name" msgid="3027315045397363079">"Բառարանի մատակարար"</string>
+ <string name="dictionary_service_name" msgid="6237472350693511448">"Բառարանի ծառայություն"</string>
+ <string name="download_description" msgid="6014835283119198591">"Տեղեկություններ բառարանների թարմացման մասին"</string>
+ <string name="dictionary_settings_title" msgid="8091417676045693313">"Ավելացնել բառարաններ"</string>
+ <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Բառարանն առկա է"</string>
+ <string name="dictionary_settings_summary" msgid="5305694987799824349">"Բառարանների կարգավորումներ"</string>
+ <string name="user_dictionaries" msgid="3582332055892252845">"Օգտվողի բառարաններ"</string>
+ <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Օգտվողի բառարան"</string>
+ <string name="dictionary_available" msgid="4728975345815214218">"Բառարանն առկա է"</string>
+ <string name="dictionary_downloading" msgid="2982650524622620983">"Այս պահին ներբեռնվում է"</string>
+ <string name="dictionary_installed" msgid="8081558343559342962">"Տեղադրված է"</string>
+ <string name="dictionary_disabled" msgid="8950383219564621762">"Տեղադրված է, անջատված է"</string>
+ <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Բառարանային ծառայությանը միացման խնդիր կա"</string>
+ <string name="no_dictionaries_available" msgid="8039920716566132611">"Բառարաններ չկան"</string>
+ <string name="check_for_updates_now" msgid="8087688440916388581">"Թարմացնել"</string>
+ <string name="last_update" msgid="730467549913588780">"Վերջին անգամ թարմացվել է"</string>
+ <string name="message_updating" msgid="4457761393932375219">"Ստուգվում է թարմացումների առկայությունը"</string>
+ <string name="message_loading" msgid="8689096636874758814">"Բեռնվում է..."</string>
+ <string name="main_dict_description" msgid="3072821352793492143">"Հիմնական բառարան"</string>
+ <string name="cancel" msgid="6830980399865683324">"Չեղարկել"</string>
+ <string name="install_dict" msgid="180852772562189365">"Տեղադրել"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"Չեղարկել"</string>
+ <string name="delete_dict" msgid="756853268088330054">"Ջնջել"</string>
+ <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"Ձեր բջջային սարքում ընտրված լեզվով առկա է բառարան:<br/> Խորհուրդ ենք տալիս &lt;b&gt;ներբեռնել&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> բառարանը ձեր մուտքագրման հմտությունների բարելավման համար:&lt;br/&gt; &lt;br/&gt; Ներբեռնումը կարող է խլել մեկ կամ երկու րոպե 3G-ի դեպքում: Հնարավոր է գանձում կատարվի, եթե դուք չունեք &lt;b&gt;տվյալների անսահմանափակ փաթեթ&lt;/b&gt;.&lt;br/&gt; Եթե դուք վստահ չեք, թե տվյալների որ փաթեթն ունեք, խորհուրդ ենք տալիս գտնել Wi-Fi կապ՝ ներբեռնումն ավտոմատ սկսելու համար:&lt;br/&gt; &lt;br/&gt; Հուշում. դուք կարող եք ներբեռնել և հեռացնել բառարաններ՝ գնալով ձեր բջջային սարքի &lt;b&gt;Կարգավորումներ ցանկի Լեզու &amp; մուտքագրման&lt;/b&gt; բաժինը:"</string>
+ <string name="download_over_metered" msgid="1643065851159409546">"Ներբեռնել հիմա (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>Մբ)"</string>
+ <string name="do_not_download_over_metered" msgid="2176209579313941583">"Ներբեռնել Wi-Fi-ով"</string>
+ <string name="dict_available_notification_title" msgid="6514288591959117288">"<xliff:g id="LANGUAGE">%1$s</xliff:g>-ով առկա է մի բառարան"</string>
+ <string name="dict_available_notification_description" msgid="1075194169443163487">"Սեղմեք՝ վերանայելու և ներբեռնելու համար"</string>
+ <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Ներբեռնվում է. <xliff:g id="LANGUAGE">%1$s</xliff:g>-ի համար առաջարկները շուտով պատրաստ կլինեն:"</string>
+ <string name="version_text" msgid="2715354215568469385">"Տարբերակ <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Ավելացնել"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Ավելացնել բառարանում"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Արտահայտություն"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Այլ ընտրանքներ"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Սակավ ընտրանքներ"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"Լավ"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Բառը՝"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Դյուրանցումը՝"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Lեզուն՝"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Մուտքագրեք բառը"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Ընտրովի դյուրանցում"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Խմբագրել բառը"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Խմբագրել"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Ջնջել"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Դուք չունեք ոչ մի բառ օգտվողի բառարանում: Ավելացնել բառեր՝ հպելով Ավելացնել (+) կոճակը:"</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Բոլոր լեզուներով"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Ավելի շատ լեզուներով..."</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"Ջնջել"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
+</resources>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index bfbd2a700..a731478a5 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Pasang headset untuk mendengar tombol sandi yang diucapkan dengan keras."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Teks saat ini adalah %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Tidak ada teks yang dimasukkan"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> mengoreksi <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> menjadi <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> melakukan koreksi otomatis"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Kode tombol %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift hidup (ketuk untuk mematikan)"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 6989643af..ec27fd5a7 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -62,7 +62,7 @@
<string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Non suggerire parole potenzialmente offensive"</string>
<string name="auto_correction" msgid="7630720885194996950">"Correzione automatica"</string>
<string name="auto_correction_summary" msgid="5625751551134658006">"Barra spaziatrice/punteggiatura correggono parole con errori"</string>
- <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Off"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"OFF"</string>
<string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Media"</string>
<string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Molto elevata"</string>
<string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Massima"</string>
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Collega gli auricolari per ascoltare la pronuncia dei tasti premuti per la password."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Il testo attuale è %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nessun testo inserito"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> corregge <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> con <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> esegue correzione automatica"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Codice tasto %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Maiuscolo"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Maiuscolo attivo (tocca per disattivare)"</string>
@@ -128,7 +126,7 @@
<string name="voice_input" msgid="3583258583521397548">"Tasto input vocale"</string>
<string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Su tastiera principale"</string>
<string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Su tastiera simboli"</string>
- <string name="voice_input_modes_off" msgid="3745699748218082014">"Non attivo"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"OFF"</string>
<string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Microfono su tastiera principale"</string>
<string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Microfono su tastiera simboli"</string>
<string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input vocale disatt."</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index b3ee01410..81d2e406d 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"חבר אוזניות כדי לשמוע הקראה של מפתחות סיסמה."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"הטקסט הנוכחי הוא %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"לא הוזן טקסט"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> מתקן את <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ל-<xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> מבצע תיקון אוטומטי"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"קוד מקש %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift פועל (הקש כדי להשבית)"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 37f06377e..fd546d9da 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -50,7 +50,7 @@
<string name="use_double_space_period_summary" msgid="6532892187247952799">"スペースバーをダブルタップするとピリオドとスペースを挿入できます"</string>
<string name="auto_cap" msgid="1719746674854628252">"自動大文字変換"</string>
<string name="auto_cap_summary" msgid="7934452761022946874">"英字入力で各文の最初の単語を大文字にします"</string>
- <string name="edit_personal_dictionary" msgid="3996910038952940420">"ユーザー辞書"</string>
+ <string name="edit_personal_dictionary" msgid="3996910038952940420">"単語リスト"</string>
<string name="configure_dictionaries_title" msgid="4238652338556902049">"アドオン辞書"</string>
<string name="main_dictionary" msgid="4798763781818361168">"メイン辞書"</string>
<string name="prefs_show_suggestions" msgid="8026799663445531637">"修正候補を表示する"</string>
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"パスワードのキーが音声出力されるのでヘッドセットを接続してください。"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"現在のテキスト:%s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"テキストが入力されていません"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g>は<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>を<xliff:g id="CORRECTED">%3$s</xliff:g>に修正します"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g>で自動修正が実行されます"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"キーコード:%d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift有効(タップして解除)"</string>
diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml
index 193f5115d..62249616f 100644
--- a/java/res/values-ka-rGE/strings.xml
+++ b/java/res/values-ka-rGE/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"შეაერთეთ ყურსაცვამი, რათა მოისმინოთ აკრეფილი პაროლის კლავიშების სახელები."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"მიმდინარე ტექსტი არის %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"ტექსტი არ შეყვანილა"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> შეასწორებს <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>-ს <xliff:g id="CORRECTED">%3$s</xliff:g>-ად"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> ასრულებს ავტოკორექციას"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"კლავიატურის კოდი %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ჩართულია (შეეხეთ გამოსართავად)"</string>
diff --git a/java/res/values-km-rKH/strings-appname.xml b/java/res/values-km-rKH/strings-appname.xml
new file mode 100644
index 000000000..e7b27072e
--- /dev/null
+++ b/java/res/values-km-rKH/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"ក្ដារចុច Android (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"កម្មវិធី​ពិនិត្យ​អក្ខរាវិរុទ្ធ Android (AOSP​)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"ការ​កំណត់​ក្ដារ​ចុច Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"កំណត់​​កម្មវិធី​ពិនិត្យ​​អក្ខរាវិរុទ្ធ​សម្រាប់ ​​Android (AOSP)"</string>
+</resources>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
new file mode 100644
index 000000000..79a0b2c9c
--- /dev/null
+++ b/java/res/values-km-rKH/strings.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_input_options" msgid="3909945612939668554">"ជម្រើស​​បញ្ចូល"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"ពាក្យ​បញ្ជា​កំណត់​ហេតុ​​ការ​ស្រាវជ្រាវ"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"រក​មើល​ឈ្មោះ​ទំនាក់ទំនង"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"កម្មវិធី​ពិនិត្យ​អក្ខរាវិរុទ្ធ​ប្រើ​ធាតុ​ពី​​ក្នុង​បញ្ជី​ទំនាក់ទំនង​របស់​អ្នក"</string>
+ <string name="vibrate_on_keypress" msgid="5258079494276955460">"ញ័រ​នៅ​ពេល​ចុច​គ្រាប់ចុច"</string>
+ <string name="sound_on_keypress" msgid="6093592297198243644">"សំឡេង​នៅ​ពេល​ចុច​គ្រាប់ចុច"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"លេច​ឡើង​នៅ​​ពេល​ចុច​គ្រាប់​ចុច"</string>
+ <string name="general_category" msgid="1859088467017573195">"ទូទៅ"</string>
+ <string name="correction_category" msgid="2236750915056607613">"ការ​កែ​អត្ថបទ"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"បញ្ចូល​ដោយ​ប្រើ​កាយវិការ"</string>
+ <string name="misc_category" msgid="6894192814868233453">"ជម្រើស​ផ្សេងទៀត"</string>
+ <string name="advanced_settings" msgid="362895144495591463">"ការ​កំណត់​កម្រិត​ខ្ពស់"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"ជម្រើស​សម្រាប់​អ្នក​ជំនាញ"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"ប្ដូរ​ទៅ​​​វិធីសាស្ត្រ​បញ្ចូល​​​ផ្សេង​ទៀត"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"គ្រាប់ចុច​ប្ដូរ​ភាសា​តាម​វិធីសាស្ត្រ​បញ្ចូល​ផ្សេងទៀត"</string>
+ <string name="show_language_switch_key" msgid="5915478828318774384">"គ្រាប់​ចុច​ប្ដូរ​​ភាសា"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"បង្ហាញ​នៅ​ពេល​ដែល​បើក​ភាសា​បញ្ចូល​ច្រើន"</string>
+ <string name="sliding_key_input_preview" msgid="6604262359510068370">"បង្ហាញ​ទ្រនិច​បង្ហាញ​ស្លាយ"</string>
+ <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"បង្ហាញ​​សញ្ញា​មើល​​ឃើញ​ខណៈ​ពេល​ដែល​រុញ​ពី​ឆ្វេង ឬ​​គ្រាប់​ចុច​​និមិត្ត​សញ្ញា"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"​សោ​លេចឡើង​បោះបង់​ការ​​ពន្យារពេល"</string>
+ <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"គ្មាន​ការ​ពន្យារពេល"</string>
+ <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"លំនាំដើម"</string>
+ <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> មិល្លី​វិនាទី"</string>
+ <string name="settings_system_default" msgid="6268225104743331821">"លំនាំ​ដើម​​​ប្រព័ន្ធ"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"ស្នើ​ឈ្មោះ​ទំនាក់ទំនង"</string>
+ <string name="use_contacts_dict_summary" msgid="6599983334507879959">"ប្រើ​ឈ្មោះ​ពី​ទំនាក់ទំនង​សម្រាប់​ការ​​ស្នើ និង​​​កែ"</string>
+ <string name="use_double_space_period" msgid="8781529969425082860">"រយៈ​ពេល​ចុច​ដកឃ្លា​ពីរដង"</string>
+ <string name="use_double_space_period_summary" msgid="6532892187247952799">"ប៉ះ​ដកឃ្លា​ពីរ​​ដង​បញ្ចូល​​​រយៈ​ពេល​ដែល​អនុវត្ត​តាម​ដកឃ្លា"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"ការ​សរសេរ​ជា​អក្សរ​ធំ​​ស្វ័យប្រវត្តិ"</string>
+ <string name="auto_cap_summary" msgid="7934452761022946874">"សរសេរ​ពាក្យ​ដំបូង​​​ជា​អក្សរ​ធំ​​នៃ​ប្រយោគ​នីមួយ​ៗ"</string>
+ <string name="edit_personal_dictionary" msgid="3996910038952940420">"វចនានុក្រម​ផ្ទាល់ខ្លួន"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"វចនានុក្រម​ចម្បង"</string>
+ <string name="prefs_show_suggestions" msgid="8026799663445531637">"បង្ហាញ​ការ​ស្នើ​​កែ"</string>
+ <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"បង្ហាញ​ពាក្យ​​បាន​​ផ្ដល់​​ស្នើ​​ខណៈ​ពេល​​​វាយ​បញ្ចូល"</string>
+ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"បង្ហាញ​ជា​និច្ច"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"បង្ហាញ​នៅ​ក្នុង​របៀប​បញ្ឈរ"</string>
+ <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"លាក់​ជានិច្ច"</string>
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"ទប់ស្កាត់​​ពាក្យ​​បំពាន"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"កុំ​ស្នើ​ឲ្យ​ពាក្យ​បំពាន​មាន​សក្ដានុពល"</string>
+ <string name="auto_correction" msgid="7630720885194996950">"ការ​កែ​​​ស្វ័យប្រវត្តិ"</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"ចន្លោះ​មិន​ឃើញ ​និង​សញ្ញា​​វណ្ណយុត្ត​កែ​ពាក្យ​ដែល​បាន​វាយ​ខុស​ស្វ័យប្រវត្តិ"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"បិទ"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ល្មម"</string>
+ <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"បំពាន"</string>
+ <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"បំពាន​ខ្លាំង"</string>
+ <string name="bigram_prediction" msgid="1084449187723948550">"ការ​ស្នើ​ពាក្យ​បន្ទាប់"</string>
+ <string name="bigram_prediction_summary" msgid="3896362682751109677">"ប្រើ​ពាក្យ​មុន​​នៅ​ពេល​ធ្វើ​ការ​​​ស្នើ"</string>
+ <string name="gesture_input" msgid="826951152254563827">"បើក​ការ​​បញ្ចូល​​កាយវិការ"</string>
+ <string name="gesture_input_summary" msgid="9180350639305731231">"បញ្ចូល​ពាក្យ​ដោយ​រំកិល​​​តាម​​អក្សរ"</string>
+ <string name="gesture_preview_trail" msgid="3802333369335722221">"បង្ហាញ​ដាន​កាយវិការ"</string>
+ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"មើល​ការ​​អណ្ដែត​ដែល​មាន​ចលនា​ជា​មុន"</string>
+ <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"​មើល​ពាក្យ​​​ដែល​បាន​ស្នើ​​​ខណៈ​ពេល​កំពុង​ធ្វើ​កាយ​វិការ"</string>
+ <string name="added_word" msgid="8993883354622484372">"បាន​រក្សាទុក <xliff:g id="WORD">%s</xliff:g> ៖"</string>
+ <string name="label_go_key" msgid="1635148082137219148">"ទៅ"</string>
+ <string name="label_next_key" msgid="362972844525672568">"បន្ទាប់"</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"មុន"</string>
+ <string name="label_done_key" msgid="2441578748772529288">"រួចរាល់"</string>
+ <string name="label_send_key" msgid="2815056534433717444">"ផ្ញើ"</string>
+ <string name="label_pause_key" msgid="181098308428035340">"ផ្អាក"</string>
+ <string name="label_wait_key" msgid="6402152600878093134">"រង់ចាំ"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"ដោត​កាស ដើម្បី​ស្ដាប់​ពាក្យ​សម្ងាត់។"</string>
+ <string name="spoken_current_text_is" msgid="2485723011272583845">"អត្ថបទ​បច្ចុប្បន្ន​គឺ %s"</string>
+ <string name="spoken_no_text_entered" msgid="7479685225597344496">"គ្មាន​អត្ថបទ​​​បាន​បញ្ចូល"</string>
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> កែ <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ទៅ <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> អនុវត្ត​ការ​កែ​ដោយស្វ័យប្រវត្តិ"</string>
+ <string name="spoken_description_unknown" msgid="3197434010402179157">"កូដ​គ្រាប់​ចុច %d"</string>
+ <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"បើក Shift (​ប៉ះ​ដើម្បី​បិទ)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"បើក Caps lock (ប៉ះ​​ដើម្បី​បិទ)"</string>
+ <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string>
+ <string name="spoken_description_to_symbol" msgid="5486340107500448969">"និមិត្ត​សញ្ញា"</string>
+ <string name="spoken_description_to_alpha" msgid="23129338819771807">"អក្សរ"</string>
+ <string name="spoken_description_to_numeric" msgid="591752092685161732">"លេខ"</string>
+ <string name="spoken_description_settings" msgid="4627462689603838099">"ការ​កំណត់"</string>
+ <string name="spoken_description_tab" msgid="2667716002663482248">"Tab"</string>
+ <string name="spoken_description_space" msgid="2582521050049860859">"ដកឃ្លា"</string>
+ <string name="spoken_description_mic" msgid="615536748882611950">"បញ្ចូលសំឡេង"</string>
+ <string name="spoken_description_smiley" msgid="2256309826200113918">"មុខ​ញញឹម"</string>
+ <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"ស្វែងរក"</string>
+ <string name="spoken_description_dot" msgid="40711082435231673">"Dot"</string>
+ <string name="spoken_description_language_switch" msgid="5507091328222331316">"ប្ដូរ​​ភាសា"</string>
+ <string name="spoken_description_action_next" msgid="8636078276664150324">"បន្ទាប់"</string>
+ <string name="spoken_description_action_previous" msgid="800872415009336208">"មុន"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"បាន​បើក Shift"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"បាន​បើក Caps lock"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"បាន​បិទ Shift"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"របៀប​និមិត្តសញ្ញា"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"របៀប​អក្សរ"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"របៀប​ទូរស័ព្ទ"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"​របៀប​និមិត្ត​សញ្ញា​ទូរស័ព្ទ"</string>
+ <string name="announce_keyboard_hidden" msgid="8718927835531429807">"បាន​លាក់​ក្ដារចុច"</string>
+ <string name="announce_keyboard_mode" msgid="4729081055438508321">"បង្ហាញ​ក្ដារ​ចុច <xliff:g id="MODE">%s</xliff:g>"</string>
+ <string name="keyboard_mode_date" msgid="3137520166817128102">"កាលបរិច្ឆេទ"</string>
+ <string name="keyboard_mode_date_time" msgid="339593358488851072">"កាល​បរិច្ឆេទ​ និង​ពេល​វេលា"</string>
+ <string name="keyboard_mode_email" msgid="6216248078128294262">"អ៊ីមែល"</string>
+ <string name="keyboard_mode_im" msgid="1137405089766557048">"​ផ្ញើ​សារ"</string>
+ <string name="keyboard_mode_number" msgid="7991623440699957069">"លេខ"</string>
+ <string name="keyboard_mode_phone" msgid="6851627527401433229">"ទូរស័ព្ទ"</string>
+ <string name="keyboard_mode_text" msgid="6479436687899701619">"អត្ថបទ"</string>
+ <string name="keyboard_mode_time" msgid="4381856885582143277">"ពេលវេលា"</string>
+ <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string>
+ <string name="voice_input" msgid="3583258583521397548">"គ្រាប់​ចុច​បញ្ចូល​​សំឡេង"</string>
+ <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"នៅ​លើ​ក្ដារចុច​ចម្បង"</string>
+ <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"នៅ​លើ​ក្ដារចុច​​និមិត្ត​សញ្ញា"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"បិទ"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"មីក្រូហ្វូន​នៅ​លើ​​ក្ដារចុច​ចម្បង"</string>
+ <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"មីក្រូហ្វូន​នៅ​លើ​​ក្ដារចុច​និមិត្ត​សញ្ញា"</string>
+ <string name="voice_input_modes_summary_off" msgid="63875609591897607">"បាន​បិទ​ការ​បញ្ចូល​សំឡេង"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"កំណត់​រចនាសម្ព័ន្ធ​វិធីសាស្ត្រ​បញ្ចូល"</string>
+ <string name="language_selection_title" msgid="1651299598555326750">"បញ្ចូល​ភាសា"</string>
+ <string name="send_feedback" msgid="1780431884109392046">"ផ្ញើ​មតិ​អ្នក​ប្រើ"</string>
+ <string name="select_language" msgid="3693815588777926848">"​​បញ្ចូល​ភាសា"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"ប៉ះ​ម្ដង​ទៀត​ ដើម្បី​រក្សា​ទុក"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"មាន​វចនានុក្រម"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"បើក​មតិត្រឡប់"</string>
+ <string name="prefs_description_log" msgid="7525225584555429211">"ជំនួយ​​​ធ្វើ​ឲ្យ​​ប្រសើរ​ឡើង​​នៃ​កម្មវិធី​កែ​​វិធី​សាស្ត្រ​​បញ្ចូល​ដោយ​ស្វ័យ​ប្រវត្តិ​ ដោយ​ផ្ញើ​ស្ថិតិ​​ប្រើ​ប្រាស់​ ​និង​របាយការណ៍​គាំង"</string>
+ <string name="keyboard_layout" msgid="8451164783510487501">"រូបរាង​ក្ដារចុច"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"អង់គ្លេស (​អង់គ្លេស)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"អង់គ្លេស (សហរដ្ឋ​អាមេរិក)"</string>
+ <string name="subtype_es_US" msgid="5583145191430180200">"អេស្ប៉ាញ (សហរដ្ឋ​អាមេរិក​)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"អង់គ្លេស (ចក្រភព​អង់គ្លេស) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"អង់គ្លេស (អាមេរិក) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"អេស្ប៉ាញ (អាមេរិក​) ( <xliff:g id="LAYOUT">%s</xliff:g> )"</string>
+ <string name="subtype_nepali_traditional" msgid="9032247506728040447">"<xliff:g id="LANGUAGE">%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>
+ <string name="subtype_no_language_azerty" msgid="8144348527575640087">"តាម​លំដាប់​អក្សរក្រម (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"តាម​លំដាប់​អក្សរក្រម (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="5837418400010302623">"តាម​លំដាប់​អក្សរក្រម (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"តាម​លំដាប់​អក្សរក្រម (កុំព្យូទ័រ)"</string>
+ <string name="subtype_emoji" msgid="7483586578074549196">"សញ្ញា​អារម្មណ៍"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"រចនាប័ទ្ម​បញ្ចូល​ផ្ទាល់ខ្លួន"</string>
+ <string name="add_style" msgid="6163126614514489951">"បន្ថែម​រចនាប័ទ្ម"</string>
+ <string name="add" msgid="8299699805688017798">"បន្ថែម"</string>
+ <string name="remove" msgid="4486081658752944606">"លុប​ចេញ"</string>
+ <string name="save" msgid="7646738597196767214">"រក្សាទុក"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"ភាសា"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"ប្លង់"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"ចាំបាច់​ត្រូវ​បើក​រចនាប័ទ្ម​បញ្ចូល​ផ្ទាល់​ខ្លួន​របស់​អ្នក មុន​ពេល​អ្នក​ចាប់ផ្ដើម​ប្រើ​វា។ តើ​អ្នក​ចង់​បើក​វា​ឥឡូវ​នេះ​ឬ?"</string>
+ <string name="enable" msgid="5031294444630523247">"បើក"</string>
+ <string name="not_now" msgid="6172462888202790482">"មិនមែន​ឥឡូវ"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"មាន​រចនាប័ទ្ម​បញ្ចូល​ដូច​គ្នា​ដូច​ហើយ៖ <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+ <string name="prefs_usability_study_mode" msgid="1261130555134595254">"របៀប​ការ​សិក្សា​ដែល​អាច​ប្រើ​បាន"</string>
+ <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"ពន្យារពេល​​​ចុច​គ្រាប់​ចុច​ឲ្យ​​យូរ"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"ថិរវេលា​​ញ័រ​​ពេល​ចុច​គ្រាប់ចុច"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"កម្រិត​សំឡេង​ពេល​ចុច​គ្រាប់​ចុច"</string>
+ <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"អាន​ឯកសារ​វចនានុក្រម​ខាង​ក្រៅ"</string>
+ <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"គ្មាន​ឯកសារ​វចនានុក្រម​នៅ​ក្នុង​ថត​ទាញ​យក"</string>
+ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"ជ្រើស​ឯកសារ​វចនានុក្រម​ ដើម្បី​ដំឡើង"</string>
+ <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"ពិត​ជា​ដំឡើង​ឯកសារ​នេះ​សម្រាប់ <xliff:g id="LOCALE_NAME">%s</xliff:g> ឬ?"</string>
+ <string name="error" msgid="8940763624668513648">"មាន​កំហុស"</string>
+ <string name="button_default" msgid="3988017840431881491">"លំនាំដើម"</string>
+ <string name="setup_welcome_title" msgid="6112821709832031715">"សូម​ស្វាគមន៍​មក​កាន់ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_welcome_additional_description" msgid="8150252008545768953">"ជាមួយ​​​ការ​វាយ​បញ្ចូល​ដោយ​ប្រើ​​​កាយវិការ"</string>
+ <string name="setup_start_action" msgid="8936036460897347708">"បាន​ចាប់ផ្ដើម"</string>
+ <string name="setup_next_action" msgid="371821437915144603">"ជំហាន​បន្ទាប់"</string>
+ <string name="setup_steps_title" msgid="6400373034871816182">"រៀបចំ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_title" msgid="3147967630253462315">"បើក <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_instruction" msgid="2578631936624637241">"សូម​ពិនិត្យ​ \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" នៅ​ក្នុង​ការ​កំណត់​ភាសា &amp; និង​ការ​បញ្ចូល​របស់​អ្នក។ វា​នឹង​ដំណើរការ​នៅ​លើ​ឧបករណ៍​របស់​អ្នក។"</string>
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>បាន​បើក​នៅ​ក្នុង​​ការ​កំណត់​​ភាសា​ &amp; ការ​បញ្ចូល​របស់ ដូច្នេះ​ជំហាន​នេះ​រួចរាល់​ហើយ។ បន្ត​ទៅ​ជំហាន​បន្ទាប់!"</string>
+ <string name="setup_step1_action" msgid="4366513534999901728">"បើក​នៅ​ក្នុង​ការ​កំណត់"</string>
+ <string name="setup_step2_title" msgid="6860725447906690594">"ប្ដូរ​ទៅ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step2_instruction" msgid="9141481964870023336">"បន្ទាប់ ជ្រើស \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" ជា​វិធី​សាស្ត្រ​បញ្ចូល​អត្ថបទ​សកម្ម​របស់​អ្នក។"</string>
+ <string name="setup_step2_action" msgid="1660330307159824337">"ប្ដូរ​វិធីសាស្ត្រ​បញ្ចូល"</string>
+ <string name="setup_step3_title" msgid="3154757183631490281">"សូម​អបអរ​សាទរ,​ អ្នក​​បាន​កំណត់​​រួចរាល់​ហើយ!"</string>
+ <string name="setup_step3_instruction" msgid="8025981829605426000">"ឥឡូវ​​អ្នក​អាច​​វាយ​បញ្ចូល​នៅ​ក្នុង​​កម្មវិធី​​ពេញ​ចិត្ត​របស់​អ្នក​ទាំងអស់​ជាមួយ <xliff:g id="APPLICATION_NAME">%s</xliff:g> ។"</string>
+ <string name="setup_step3_action" msgid="600879797256942259">"កំណត់​រចនា​សម្ព័ន្ធ​ភាសា​បន្ថែម"</string>
+ <string name="setup_finish_action" msgid="276559243409465389">"បាន​បញ្ចប់"</string>
+ <string name="show_setup_wizard_icon" msgid="5008028590593710830">"បង្ហាញ​រូប​តំណាង​កម្មវិធី"</string>
+ <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"បង្ហាញ​រូប​តំណាង​កម្មវិធី​នៅ​ក្នុង​កម្ម​​វិធី​ចាប់ផ្ដើម"</string>
+ <string name="app_name" msgid="6320102637491234792">"កម្មវិធី​ផ្ដល់​វចនានុក្រម"</string>
+ <string name="dictionary_provider_name" msgid="3027315045397363079">"កម្មវិធី​ផ្ដល់​វចនានុក្រម"</string>
+ <string name="dictionary_service_name" msgid="6237472350693511448">"សេវាកម្ម​​វចនានុក្រម"</string>
+ <string name="download_description" msgid="6014835283119198591">"ព័ត៌មាន​បច្ចុប្បន្នភាព​វចនានុក្រម"</string>
+ <string name="dictionary_settings_title" msgid="8091417676045693313">"ផ្នែក​បន្ថែម​វចនានុក្រម"</string>
+ <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"វចនានុក្រម​​​​​អាច​ប្រើ​បាន"</string>
+ <string name="dictionary_settings_summary" msgid="5305694987799824349">"ការ​កំណត់​សម្រាប់​វចនានុក្រម"</string>
+ <string name="user_dictionaries" msgid="3582332055892252845">"វចនានុក្រម​​​អ្នក​ប្រើ"</string>
+ <string name="default_user_dict_pref_name" msgid="1625055720489280530">"វចនានុក្រម​អ្នកប្រើ"</string>
+ <string name="dictionary_available" msgid="4728975345815214218">"វចនានុក្រម​​​អាច​ប្រើ​បាន"</string>
+ <string name="dictionary_downloading" msgid="2982650524622620983">"បច្ចុប្បន្ន​កំពុង​ទាញ​យក"</string>
+ <string name="dictionary_installed" msgid="8081558343559342962">"បាន​ដំឡើង"</string>
+ <string name="dictionary_disabled" msgid="8950383219564621762">"បាន​ដំឡើង បាន​បិទ"</string>
+ <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"មាន​បញ្ហា​ក្នុង​ការ​​ភ្ជាប់​ទៅ​​សេវា​កម្ម​វចនានុក្រម"</string>
+ <string name="no_dictionaries_available" msgid="8039920716566132611">"គ្មាន​វចនានុក្រម"</string>
+ <string name="check_for_updates_now" msgid="8087688440916388581">"ផ្ទុក​ឡើងវិញ"</string>
+ <string name="last_update" msgid="730467549913588780">"បាន​ធ្វើ​បច្ចុប្បន្នភាព​ចុងក្រោយ"</string>
+ <string name="message_updating" msgid="4457761393932375219">"ពិនិត្យមើល​បច្ចុប្បន្នភាព"</string>
+ <string name="message_loading" msgid="8689096636874758814">"កំពុង​ផ្ទុក..."</string>
+ <string name="main_dict_description" msgid="3072821352793492143">"វចនានុក្រម​ចម្បង"</string>
+ <string name="cancel" msgid="6830980399865683324">"បោះ​បង់"</string>
+ <string name="install_dict" msgid="180852772562189365">"ដំឡើង"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"បោះ​បង់"</string>
+ <string name="delete_dict" msgid="756853268088330054">"លុប"</string>
+ <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"ភាសា​ដែល​បាន​ជ្រើស​នៅ​លើ​ឧបករណ៍​របស់​អ្នក​មាន​វចនានុក្រម។ &lt;br/&gt; យើង​បាន​ផ្ដល់​អនុសាសន៍ &lt;b&gt;ទាញ​យក​&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> វចនានុក្រម ដើម្បី​ធ្វើ​ឲ្យ​ការ​វាយ​បញ្ចូល​របស់​អ្នក​ប្រសើរ​ឡើង។ &lt;br/&gt; &lt;br/&gt; ការ​ទាញ​យក​អាច​ចំណាយ​ពេល​​មួយ ឬ​ពីរ​នាទី​​​តាម 3G ។ ការ​​កាត់​លុយ​អាច​អនុវត្ត​ ប្រសិន​​​បើ​អ្នក​​បាន​​ &lt;b&gt;កំណត់​ទិន្នន័យ​គ្មាន​ដែន​កំណត់ &lt;/b&gt;.&lt;br/&gt; ប្រសិនបើ​​អ្នក​មិន​ប្រាកដ​​ថា​ទិន្នន័យ​អ្នក​​មិន​បាន​​កំណត់ យើង​បាន​ផ្ដល់​អនុសាសន៍​ដោយ​ស្វែងរក​ការ​ភ្ជាប់​​វ៉ាយហ្វាយ ដើម្បី​ចាប់ផ្ដើម​ទាញ​យក​ដោយ​ស្វ័យប្រវត្តិ។&lt;br/&gt; &lt;br/&gt; ព័ត៌មាន​ជំនួយ៖ អ្នក​អាច​ទាញ​យក និង​លុប​​វចនានុក្រម​​ដោយ​ចូល​ទៅ​ &lt;b&gt;ភាសា&amp; បញ្ចូល&lt;/b&gt;​នៅ​ក្នុង​ម៉ឺនុយ &lt;b&gt;ការ​កំណត់ &lt;/b&gt; របស់​ឧបករណ៍​ចល័ត។"</string>
+ <string name="download_over_metered" msgid="1643065851159409546">"ទាញ​យក​ឥឡូវ​នេះ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> មេកាបៃ)"</string>
+ <string name="do_not_download_over_metered" msgid="2176209579313941583">"ទាញ​យក​តាម​វ៉ាយហ្វាយ"</string>
+ <string name="dict_available_notification_title" msgid="6514288591959117288">"វចនានុក្រម​​អាច​ប្រើ​បាន​​សម្រាប់ <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+ <string name="dict_available_notification_description" msgid="1075194169443163487">"ចុច​ ដើម្បី​ពិនិត្យ​មើល​ឡើង​​វិញ​ និង​ទាញ​យក"</string>
+ <string name="toast_downloading_suggestions" msgid="1313027353588566660">"ទាញ​យក៖ ការ​​ស្នើ​សម្រាប់ <xliff:g id="LANGUAGE">%1$s</xliff:g> នឹង​បញ្ចប់​ឆាប់ៗ។"</string>
+ <string name="version_text" msgid="2715354215568469385">"កំណែ <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"បន្ថែម"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"បន្ថែម​ទៅ​វចនានុក្រម"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"ឃ្លា"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"ជម្រើស​ច្រើន"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"ជម្រើស​តិច"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"យល់ព្រម"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"ពាក្យ៖"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"ផ្លូវកាត់​៖"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"ភាសា៖"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"វាយ​បញ្ចូល​ពាក្យ"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"ផ្លូវកាត់​ជា​ជម្រើស"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"កែ​ពាក្យ"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"កែ"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"លុប"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"អ្នក​មិន​មាន​ពាក្យ​ណាមួយ​នៅ​ក្នុង​វចនានុក្រម​អ្នក​ប្រើ​ទេ។ បន្ថែម​ពាក្យ​ដោយ​​​​ប៉ះ​ប៊ូតុង​ បន្ថែម ​ (+)។"</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"សម្រាប់​ភាសា​ទាំងអស់"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"ភាសា​ច្រើន​ទៀត…"</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"លុប"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+</resources>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index 1497812e9..255e23440 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"비밀번호 키를 음성으로 들으려면 헤드셋을 연결하세요."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"입력한 텍스트: %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"입력한 텍스트 없음"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g>을(를) 누르면 <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>을(를) <xliff:g id="CORRECTED">%3$s</xliff:g>(으)로 수정합니다."</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g>을(를) 누르면 자동 수정됩니다."</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"키 코드 %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"시프트 키"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift 사용(사용하지 않으려면 탭하세요.)"</string>
diff --git a/java/res/values-lo-rLA/strings-appname.xml b/java/res/values-lo-rLA/strings-appname.xml
new file mode 100644
index 000000000..17a009483
--- /dev/null
+++ b/java/res/values-lo-rLA/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"ແປ້ນພິມ Android (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"ໂຕກວດການສະກົດຄຳໃນ Android (AOSP)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"ຕັ້ງຄ່າແປ້ນພິມ Android (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"Android Spell Checker Settings (AOSP)"</string>
+</resources>
diff --git a/java/res/values-lo-rLA/strings.xml b/java/res/values-lo-rLA/strings.xml
new file mode 100644
index 000000000..1597f9237
--- /dev/null
+++ b/java/res/values-lo-rLA/strings.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_input_options" msgid="3909945612939668554">"ຕົວເລືອກການປ້ອນຂໍ້ມູນ"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"Research Log Commands"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"ເບິ່ງທີ່ຊື່ຂອງລາຍຊື່ຜູ່ຕິດຕໍ່"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"ໂຕຊ່ວຍສະກົດໃຊ້ຂໍ້ມູນຈາກລາຍການຂອງລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານ"</string>
+ <string name="vibrate_on_keypress" msgid="5258079494276955460">"ສັ່ນເຕືອນເມື່ອພິມ"</string>
+ <string name="sound_on_keypress" msgid="6093592297198243644">"ສຽງໃນການກົດປຸ່ມ"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"ໂຕອັກສອນເວລາພິມ"</string>
+ <string name="general_category" msgid="1859088467017573195">"ທົ່ວໄປ"</string>
+ <string name="correction_category" msgid="2236750915056607613">"ໂຕຊ່ວຍແປງຂໍ້ຄວາມ"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"ການພິມແບບ Gesture"</string>
+ <string name="misc_category" msgid="6894192814868233453">"ໂຕເລືອກ​ອື່ນໆ"</string>
+ <string name="advanced_settings" msgid="362895144495591463">"ການຕັ້ງຄ່າຂັ້ນສູງ"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"ຕົວເລືອກສຳລັບຜູ່ທີ່ຊຳນານ"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"ປ່ຽນໄປໃຊ້ການປ້ອນຂໍ້ມູນແບບອື່ນ"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"ໂຕປ່ຽນພາສາເປັນທັງໂຕປ່ຽນຮູບແບບການປ້ອນຂໍ້ມູນເຊັ່ນກັນ"</string>
+ <string name="show_language_switch_key" msgid="5915478828318774384">"ປຸ່ມປ່ຽນພາສາ"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"ສະແດງໃນເວລາທີ່ຕົວເລືອກການປ້ອນຂໍ້ມູນຫຼາຍໂຕຖືກເປີດຢູ່"</string>
+ <string name="sliding_key_input_preview" msgid="6604262359510068370">"ສະແດງໂຕບົ່ງບອກການສະໄລ້"</string>
+ <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"ສະແດງແນວທາງໃນຂະນະທີ່ສະໄລ້ຈາກ Shift ຫຼື ປຸ່ມເຄື່ອງໝາຍ"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"ໄລຍະເວລາການສະແດງໂຕອັກສອນ"</string>
+ <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"ບໍ່ຕ້ອໜ່ວງເວລາ"</string>
+ <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ຄ່າເລີ່ມຕົ້ນ"</string>
+ <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g>ms"</string>
+ <string name="settings_system_default" msgid="6268225104743331821">"ຄ່າເລີ່ມຕົ້ນຂອງລະບົບ"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"ແນະນຳລາຍຊື່ຜູ່ຕິດຕໍ່"</string>
+ <string name="use_contacts_dict_summary" msgid="6599983334507879959">"ໃຊ້ຊື່ຈາກລາຍຊື່ຜູ່ຕິດຕໍ່ສຳລັບການແນະນຳ ແລະ ການຊ່ວຍແກ້ຄຳ"</string>
+ <string name="use_double_space_period" msgid="8781529969425082860">"ຍະຫວ່າງສອງເທື່ອເພື່ອໃສ່ຈ້ຳເມັດ"</string>
+ <string name="use_double_space_period_summary" msgid="6532892187247952799">"ກົດທີ່ປຸ່ມຍະຫວ່າງສອງເທື່ອເພື່ອໃສ່ຈ້ຳເມັດແລ້ວຕາມດ້ວຍການຍະຫວ່າງ"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"ເຮັດໂຕພິມໃຫຍ່ອັດຕະໂນມັດ"</string>
+ <string name="auto_cap_summary" msgid="7934452761022946874">"ເຮັດໂຕພິມໃຫຍ່ໃຫ້ໂຕອັກສອນທຳອິດຂອງແຕ່ລໃນປະໂຫຍກ"</string>
+ <string name="edit_personal_dictionary" msgid="3996910038952940420">"ວັດຈະນານຸກົມສ່ວນໂຕ"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"ໂຕເສີມວັດຈະນານຸກົມ"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"ວັດຈະນານຸກົມຫຼັກ"</string>
+ <string name="prefs_show_suggestions" msgid="8026799663445531637">"ສະແດງການແນະນຳຄຳທີ່ຖືກຕ້ອງ"</string>
+ <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"ສະແດງຄຳສັບທີ່ແນະນຳໃນເວລາທີ່ກຳລັງພິມ"</string>
+ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"ສະແດງຕະຫລອດ"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"ກົດທີ່ຄຳສັບທີ່ພິມລົງໄປເພື່ອແປງໃຫ້ມັນຖືກຕ້ອງ"</string>
+ <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"ເຊື່ອງໄວ້ຕະຫລອດ"</string>
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"ປິດກັ້ນຄຳທີ່ບໍ່ສຸພາບ"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"ຫ້າມແນະນຳຄຳທີ່ບໍ່ສຸພາບ"</string>
+ <string name="auto_correction" msgid="7630720885194996950">"ໂຕຊ່ວຍສະກົດຄຳ"</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"ການຍະຫວ່າງ ແລະ ການໃສ່ເຄື່ອງໝາຍຈະຖືກປ່ຽນແປງໃຫ້ຖືກຕ້ອງ ໃນຄຳທີ່ພິມຜິດໂດຍອັດຕະໂນມັດ"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"ປິດ"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"ປານກາງ"</string>
+ <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"ສູງ"</string>
+ <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"ສູງສຸດ"</string>
+ <string name="bigram_prediction" msgid="1084449187723948550">"ການແນະນຳຄຳຕໍ່ໄປ"</string>
+ <string name="bigram_prediction_summary" msgid="3896362682751109677">"ໃຊ້ຄຳທີ່ຜ່ານມາໃນການແນະນຳຄຳ"</string>
+ <string name="gesture_input" msgid="826951152254563827">"ເປີດນຳໃຊ້ການພິມແບບ Gesture"</string>
+ <string name="gesture_input_summary" msgid="9180350639305731231">"ໃສ່ຄຳສັບລົງໄປໂດຍການສະໄລ້ຜ່ານໂຕອັກສອນ"</string>
+ <string name="gesture_preview_trail" msgid="3802333369335722221">"ສະແດງຫາງຂອງ Gesture"</string>
+ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"ມີຄຳຕົວຢ່າງລອຍຂຶ້ນມາ"</string>
+ <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"ເບິ່ງຄຳທີ່ຖືກແນະນຳໃນເວລາທີ່ກຳລັງຊີ້"</string>
+ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ບັນທຶກແລ້ວ"</string>
+ <string name="label_go_key" msgid="1635148082137219148">"ໄປ"</string>
+ <string name="label_next_key" msgid="362972844525672568">"ຕໍ່ໄປ"</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"ກ່ອນໜ້າ"</string>
+ <string name="label_done_key" msgid="2441578748772529288">"ແລ້ວໆ"</string>
+ <string name="label_send_key" msgid="2815056534433717444">"ສົ່ງ"</string>
+ <string name="label_pause_key" msgid="181098308428035340">"ຄ້າງໄວ້"</string>
+ <string name="label_wait_key" msgid="6402152600878093134">"ລໍຖ້າ"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"ສຽບສາຍຫູຟັງເພື່ອຟັງລະຫັດຜ່ານ."</string>
+ <string name="spoken_current_text_is" msgid="2485723011272583845">"ຂໍ້ຄວາມປະຈຸບັນແມ່ນ %s"</string>
+ <string name="spoken_no_text_entered" msgid="7479685225597344496">"ບໍ່ມີການໃສ່ຂໍ້ຄວາມ"</string>
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> ແກ້ໄຂ <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ເປັນ <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> ປະຕິບັດການແປງຄຳຜິດອັດຕະໂນມັດ"</string>
+ <string name="spoken_description_unknown" msgid="3197434010402179157">"ລະຫັດກະແຈ %d"</string>
+ <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ເປີດນຳໃຊ້ຢູ່ (ກົດເພື່ອປິດນຳໃຊ້)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock ເປີດຢູ່ (ກົດເພື່ອປິດນຳໃຊ້)"</string>
+ <string name="spoken_description_delete" msgid="8740376944276199801">"ລຶບ"</string>
+ <string name="spoken_description_to_symbol" msgid="5486340107500448969">"ສັນຍາລັກ"</string>
+ <string name="spoken_description_to_alpha" msgid="23129338819771807">"ໂຕອັກ​ສອນ"</string>
+ <string name="spoken_description_to_numeric" msgid="591752092685161732">"ໂຕເລກ"</string>
+ <string name="spoken_description_settings" msgid="4627462689603838099">"ການຕັ້ງຄ່າ"</string>
+ <string name="spoken_description_tab" msgid="2667716002663482248">"ແທັບ"</string>
+ <string name="spoken_description_space" msgid="2582521050049860859">"ຍະຫວ່າງ"</string>
+ <string name="spoken_description_mic" msgid="615536748882611950">"ການປ້ອນຂໍ້ມູນດ້ວຍສຽງ"</string>
+ <string name="spoken_description_smiley" msgid="2256309826200113918">"ຮອຍຍິ້ມ"</string>
+ <string name="spoken_description_return" msgid="8178083177238315647">"ກັບຄືນ"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"ຊອກຫາ"</string>
+ <string name="spoken_description_dot" msgid="40711082435231673">"ຈ້ຳ"</string>
+ <string name="spoken_description_language_switch" msgid="5507091328222331316">"ສະລັບພາສາ"</string>
+ <string name="spoken_description_action_next" msgid="8636078276664150324">"ຕໍ່ໄປ"</string>
+ <string name="spoken_description_action_previous" msgid="800872415009336208">"ກ່ອນໜ້າ"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ເປີດນຳໃຊ້ຢູ່"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ເປີດນຳໃຊ້ຢູ່"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift ປິດນຳໃຊ້ຢູ່"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"ໂຫມດສັນຍາລັກ"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"ໂຫມດ​ໂຕອັກ​ສອນ"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"ໂຫມດໂທລະສັບ"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"ໂຫມດສັນຍາລັກໂທລະສັບ"</string>
+ <string name="announce_keyboard_hidden" msgid="8718927835531429807">"ແປ້ນ​ພິມ​ເຊື່ອງ​ໄວ້"</string>
+ <string name="announce_keyboard_mode" msgid="4729081055438508321">"ກຳລັງສະແດງແປ້ນພິມ <xliff:g id="MODE">%s</xliff:g>"</string>
+ <string name="keyboard_mode_date" msgid="3137520166817128102">"ວັນທີ"</string>
+ <string name="keyboard_mode_date_time" msgid="339593358488851072">"ວັນ​ທີ​ແລະ​ເວ​ລາ"</string>
+ <string name="keyboard_mode_email" msgid="6216248078128294262">"email"</string>
+ <string name="keyboard_mode_im" msgid="1137405089766557048">"ຂໍ້ຄວາມ"</string>
+ <string name="keyboard_mode_number" msgid="7991623440699957069">"ໂຕເລກ"</string>
+ <string name="keyboard_mode_phone" msgid="6851627527401433229">"ໂທລະສັບ"</string>
+ <string name="keyboard_mode_text" msgid="6479436687899701619">"ຂໍ້ຄວາມ"</string>
+ <string name="keyboard_mode_time" msgid="4381856885582143277">"ເວລາ"</string>
+ <string name="keyboard_mode_url" msgid="1519819835514911218">"URL"</string>
+ <string name="voice_input" msgid="3583258583521397548">"ປຸ່ມປ້ອນຂໍ້ມູນດ້ວຍສຽງ"</string>
+ <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"ແປ້ນພິມຫຼັກ"</string>
+ <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"ໃນແປ້ນພິມສັນຍາລັກ"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"ປິດ"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ໄມໃນແປ້ນພິມຫຼັກ"</string>
+ <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"ໄມໃນແປ້ນພິມສັນຍາລັກ"</string>
+ <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ການປ້ອນຂໍ້ມູນດ້ວຍສຽງປິດນຳໃຊ້ຢູ່"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"ຕັ້ງຄ່າຮູບແບບການປ້ອນຂໍ້ມູນ"</string>
+ <string name="language_selection_title" msgid="1651299598555326750">"ພາສາການປ້ອນຂໍ້ມູນ"</string>
+ <string name="send_feedback" msgid="1780431884109392046">"ສົ່ງຄຳຕິຊົມ"</string>
+ <string name="select_language" msgid="3693815588777926848">"ພາສາການປ້ອນຂໍ້ມູນ"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"ກົດອີກຄັ້ງເພື່ອບັນທຶກ"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"ມີວັດຈະນານຸກົມ"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"ເປີດນຳໃຊ້ຄຳຕິຊົມຈາກຜູ່ໃຊ້"</string>
+ <string name="prefs_description_log" msgid="7525225584555429211">"ຊ່ວຍເພີ່ມປະສິດທິພາບໂຕແກ້ໄຂການປ້ອນຂໍ້ມູນ ໂດຍການສົ່ງສະຖິຕິການນຳໃຊ້ ແລະການລາຍການຂໍ້ຜິດພາດໂດຍອັດຕະໂນມັດ"</string>
+ <string name="keyboard_layout" msgid="8451164783510487501">"ສີສັນແປ້ນພິມ"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"ອັງກິດ (ສະຫະລາດຊະອານາຈັກ)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"ອັງກິດ (ສະຫະລັດຯ)"</string>
+ <string name="subtype_es_US" msgid="5583145191430180200">"ສະເປນ (ອາເມລິກາ)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"ພາສາອັງກິດ (ອັງກິດ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"ອັງກິດ (ອາເມລິກາ) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"ແອສປາໂຍນ (ສະ​ຫະ​ລັດ​) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_nepali_traditional" msgid="9032247506728040447">"<xliff:g id="LANGUAGE">%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>
+ <string name="subtype_no_language_azerty" msgid="8144348527575640087">"ໂຕອັກສອນ (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"ໂຕອັກສອນ (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="5837418400010302623">"ໂຕອັກສອນ (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ໂຕອັກສອນ (PC)"</string>
+ <string name="subtype_emoji" msgid="7483586578074549196">"ອີໂມຈິ"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"ຮູບແບບການປ້ອນຂໍ້ມູນສ່ວນຕົວ"</string>
+ <string name="add_style" msgid="6163126614514489951">"ເພີ່ມຮູບແບບ"</string>
+ <string name="add" msgid="8299699805688017798">"ເພີ່ມ"</string>
+ <string name="remove" msgid="4486081658752944606">"ລຶບອອກ"</string>
+ <string name="save" msgid="7646738597196767214">"ບັນທຶກ"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"ພາສາ"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"ຮູບແບບ"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"ຮູບແບບການປ້ອນຂໍ້ມູນແບບສ່ວນຕົວຂອງທ່ານ ຕ້ອງຖືກເປີດນຳໃຊ້ຢູ່ກ່ອນທີ່ທ່ານຈະສາມາດໃຊ້ມັນໄດ້. ທ່ານຕ້ອງການທີ່ຈະເປີດໃຊ້ມັນດຽວນີ້ບໍ່?"</string>
+ <string name="enable" msgid="5031294444630523247">"ເປີດນຳໃຊ້"</string>
+ <string name="not_now" msgid="6172462888202790482">"ບໍ່ແມ່ນຕອນນີ້"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"ຮູບແບບການປ້ອນຂໍ້ມູນທີ່ຄືກັນມີຢູ່ແລ້ວ: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+ <string name="prefs_usability_study_mode" msgid="1261130555134595254">"ໂໝດການສຶກສາ Usability"</string>
+ <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"ໄລຍະເວລາຂອງການກົດປຸ່ມ"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"ໄລຍະເວລາຂອງການສັ່ນໃນການກົດປຸ່ມ"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"ລະດັບສຽງຂອງການກົດປຸ່ມ"</string>
+ <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"ອ່ານໄຟລ໌ວັດຈະນານຸກົມພາຍນອກ"</string>
+ <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"ບໍ່ມີໄຟລ໌ວັດຈະນານຸກົມໃນໂຟນເດີຂອງການດາວໂຫລດ"</string>
+ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"ເລືອກໄຟລ໌ວັດຈະນານຸກົມເພື່ອຕິດຕັ້ງ"</string>
+ <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"ຕິດຕັ້ງໄຟລ໌ນີ້ສຳລັບ <xliff:g id="LOCALE_NAME">%s</xliff:g> ແທ້ບໍ່?"</string>
+ <string name="error" msgid="8940763624668513648">"ມີຂໍ້ຜິດພາດເກີດຂຶ້ນ"</string>
+ <string name="button_default" msgid="3988017840431881491">"ຄ່າເລີ່ມຕົ້ນ"</string>
+ <string name="setup_welcome_title" msgid="6112821709832031715">"ຍິນ​ດີ​ຕ້ອນ​ຮັບສູ່ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_welcome_additional_description" msgid="8150252008545768953">"ດ້ວຍການພິມແບບ Gesture"</string>
+ <string name="setup_start_action" msgid="8936036460897347708">"ເລີ່ມຕົ້ນ"</string>
+ <string name="setup_next_action" msgid="371821437915144603">"ຂັ້ນຕອນຕໍ່ໄປ"</string>
+ <string name="setup_steps_title" msgid="6400373034871816182">"ຕັ້ງຄ່າ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_title" msgid="3147967630253462315">"ເປີດນຳໃຊ້ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step1_instruction" msgid="2578631936624637241">"ກະລຸນາກວດເບິ່ງ \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" ໃນການຕັ້ງຄ່າພາສາ &amp; ການປ້ອນຂໍ້ມູນຂອງທ່ານ. ນີ້ຈະເປັນການອະນຸຍາດໃຫ້ມັນເຮັດວຽກໃນອຸປະກອນຂອງທ່ານ"</string>
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ຖືກເປີດນຳໃຊ້ໃນການຕັ້ງຄ່າພາສາ &amp; ການປ້ອນຂໍ້ມູນຂອງທ່ານແລ້ວ, ສະນັ້ນຂັ້ນຕອນນີ້ແມ່ນສຳເລັດໄປແລ້ວ. ໄປທີ່ຂັ້ນຕອນຕໍ່ໄປ!"</string>
+ <string name="setup_step1_action" msgid="4366513534999901728">"ເປີດນຳໃຊ້ໃນການຕັ້ງຄ່າ"</string>
+ <string name="setup_step2_title" msgid="6860725447906690594">"ປ່ຽນເປັນ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+ <string name="setup_step2_instruction" msgid="9141481964870023336">"ຕໍ່ໄປ, ເລືອກເອົາ \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" ເປັນຮູບແບບການປ້ອນຂໍ້ມູນຂອງທ່ານ."</string>
+ <string name="setup_step2_action" msgid="1660330307159824337">"ປ່ຽນຮູບແບບການປ້ອນຂໍ້ມູນ"</string>
+ <string name="setup_step3_title" msgid="3154757183631490281">"ຍິນດີດ້ວຍ, ທ່ານເຮັດແລ້ວໆ!"</string>
+ <string name="setup_step3_instruction" msgid="8025981829605426000">"ຕອນນີ້ທ່ານສາມາດພິມໃນແອັບຯທີ່ທ່ານມັກໄດ້ທຸກແອັບຯດ້ວຍ <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
+ <string name="setup_step3_action" msgid="600879797256942259">"ປັບຄ່າພາສາເພີ່ມເຕີມ"</string>
+ <string name="setup_finish_action" msgid="276559243409465389">"ສຳເລັດແລ້ວ"</string>
+ <string name="show_setup_wizard_icon" msgid="5008028590593710830">"ສະແດງໄອຄອນຂອງແອັບຯ"</string>
+ <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"ສະແດງໄອຄອນຂອງແອັບຯໃນ Launcher"</string>
+ <string name="app_name" msgid="6320102637491234792">"ຜູ່​ສະ​ຫນອງ​ວັດຈະ​ນາ​ນຸ​ກົມ"</string>
+ <string name="dictionary_provider_name" msgid="3027315045397363079">"ຜູ່​ສະ​ຫນອງ​ວັດຈະ​ນາ​ນຸ​ກົມ"</string>
+ <string name="dictionary_service_name" msgid="6237472350693511448">"ບໍລິການວັດຈະນານຸກົມ"</string>
+ <string name="download_description" msgid="6014835283119198591">"ຂໍ້ມູນການອັບເດດວັດຈະນານຸກົມ"</string>
+ <string name="dictionary_settings_title" msgid="8091417676045693313">"ໂຕເສີມວັດຈະນານຸກົມ"</string>
+ <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"ມີວັດຈະນານຸກົມ"</string>
+ <string name="dictionary_settings_summary" msgid="5305694987799824349">"ການຕັ້ງຄ່າສຳລັບວັດຈະນານຸກົມ"</string>
+ <string name="user_dictionaries" msgid="3582332055892252845">"ວັດຈະນານຸກົມຜູ່ໃຊ້"</string>
+ <string name="default_user_dict_pref_name" msgid="1625055720489280530">"ວັດຈະນານຸກົມຜູ່ໃຊ້"</string>
+ <string name="dictionary_available" msgid="4728975345815214218">"ມີວັດຈະນານຸກົມ"</string>
+ <string name="dictionary_downloading" msgid="2982650524622620983">"ກຳລັງດາວໂຫລດ"</string>
+ <string name="dictionary_installed" msgid="8081558343559342962">"ຕິດຕັ້ງແລ້ວ"</string>
+ <string name="dictionary_disabled" msgid="8950383219564621762">"ຕິດຕັ້ງແລ້ວ, ປິດການນຳໃຊ້ແລ້ວ"</string>
+ <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"ມີປັນຫາໃນການເຊື່ອມຕໍ່ກັບບໍລິການວັດຈະນານຸກົມ"</string>
+ <string name="no_dictionaries_available" msgid="8039920716566132611">"ບໍ່ມີວັດຈະນານຸກົມ"</string>
+ <string name="check_for_updates_now" msgid="8087688440916388581">"ດຶງຂໍ້ມູນໃຫມ່"</string>
+ <string name="last_update" msgid="730467549913588780">"ອັບເດດຫຼ້າສຸດ"</string>
+ <string name="message_updating" msgid="4457761393932375219">"ກຳລັງກວດການອັບເດດ"</string>
+ <string name="message_loading" msgid="8689096636874758814">"ກຳລັງໂຫລດ..."</string>
+ <string name="main_dict_description" msgid="3072821352793492143">"ວັດຈະນານຸກົມຫຼັກ"</string>
+ <string name="cancel" msgid="6830980399865683324">"ຍົກເລີກ"</string>
+ <string name="install_dict" msgid="180852772562189365">"ຕິດຕັ້ງ"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"ຍົກເລີກ"</string>
+ <string name="delete_dict" msgid="756853268088330054">"ລຶບ"</string>
+ <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"ພາສາທີ່ທ່ານເລືອກໃຊ້ໃນອຸປະກອນຂອງທ່ານນັ້ນ ມີວັດຈະນານຸກົມໃຫ້ໃຊ້ພ້ອມ.&lt;br/&gt; ພວກເຮົາແນະນຳໃຫ້ &lt;b&gt;ດາວໂຫລດ&lt;/b&gt; <xliff:g id="LANGUAGE">%1$s</xliff:g> ວັດຈະນານຸກົມດັ່ງກ່າວ ເພື່ອເພີ່ມປະສົບການໃນການພິມຂອງທ່ານ.&lt;br/&gt; &lt;br/&gt; ການດາວໂຫລດອາດຈະໃຊ້ເວລາພຽງໜຶ່ງເຖິງສອງນາທີ ໂດຍການໃຊ້ 3G. ທ່ານອາດຈະເສຍຄ່າບໍລິການສຳລັບອິນເຕີເນັດ ຫາກທ່ານບໍ່ມີ &lt;b&gt;ການນຳໃຊ້ອິນເຕີເນັດແບບບໍ່ຈຳກັດ&lt;/b&gt;.&lt;br/&gt; ຫາກທ່ານບໍ່ແນ່ໃຈວ່າຮູບແບບການໃຊ້ໃດທີ່ທ່ານມີຢູ່ ພວກເຮົາແນະນຳໃຫ້ຊອກຫາການເຊື່ອມຕໍ່ Wi-Fi ເພື່ອດາວໂຫລດມັນໂດຍອັດຕະໂນມັດ.&lt;br/&gt; &lt;br/&gt; ເຄັດລັບ: ທ່ານສາມາດດາວໂຫລດ ແລະ ລຶບວັດຈະນານຸກົມໄດ້ທີ່ &lt;b&gt;ພາສາ &amp; ການປ້ອນຂໍ້ມູນ&lt;/b&gt; ຢູ່ໃນເມນູ &lt;b&gt;ການຕັ້ງຄ່າ&lt;/b&gt; ຂອງອຸປະກອນພົກພາຂອງທ່ານ."</string>
+ <string name="download_over_metered" msgid="1643065851159409546">"ດາວໂຫລດດຽວນີ້ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+ <string name="do_not_download_over_metered" msgid="2176209579313941583">"ດາວ​ໂຫລດຜ່ານ Wi-Fi"</string>
+ <string name="dict_available_notification_title" msgid="6514288591959117288">"ວັດຈະນານຸກົມສາມາດໃຊ້ໄດ້ກັບ <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
+ <string name="dict_available_notification_description" msgid="1075194169443163487">"ກົດທີ່ກວດຄືນ ແລະ ດາວໂຫລດ"</string>
+ <string name="toast_downloading_suggestions" msgid="1313027353588566660">"ກຳລັງດາວໂຫລດ: ການແນະນຳສຳລັບ <xliff:g id="LANGUAGE">%1$s</xliff:g> ແລະມັນຈະພ້ອມນຳໃຊ້ໄວໆນີ້"</string>
+ <string name="version_text" msgid="2715354215568469385">"ເວີຊັນ <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"ເພີ່ມ"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"ເພີ່ມໄປທີ່ວັດຈະນານຸກົມ"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"ປະໂຫຍກ"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"ຕົວເລືອກເພີ່ມເຕີມ"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"ຕົວເລືອກໜ້ອຍລົງ"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"ຕົກລົງ"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"ຄຳສັບ:"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"ທາງລັດ:"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"ພາສາ:"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"ພິມ​ຄໍາ​ສັບ​ໃດ​ນຶ່ງ"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"ໂຕເລືອກທາງລັດ"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"ແກ້ໄຂຄຳສັບ"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"ແກ້ໄຂ"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"ລຶບ"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"ທ່ານບໍ່ມີຄຳສັບໃດໆໃນວັດຈະນານຸກົມຜູ່ໃຊ້ເທື່ອ. ເພີ່ມຄຳສັບໄດ້ໂດຍການສຳພັດທີ່ປຸ່ມ ເພີ່ມ (+)."</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"ສໍາ​ລັບ​ທຸກໆ​ພາ​ສາ"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"ພາສາອື່ນໆ..."</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"ລຶບ"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+</resources>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index 88328db7d..1cb84d00b 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Prijunkite ausines, kad išgirstumėte sakomus slaptažodžio klavišus."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Dabartinis tekstas yra %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nėra įvesto teksto"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> pataiso „<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>“ į „<xliff:g id="CORRECTED">%3$s</xliff:g>“"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> atlieka automatinį taisymą"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Klavišo kodas %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Antrojo lygio klavišas"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Įjungtas antrasis lygis (palieskite, kad išjungtumėte)"</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 069c48701..221cc2e05 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Pievienojiet austiņas, lai dzirdētu paroles rakstzīmes."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Pašreizējais teksts ir %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nav ievadīts teksts"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Nospiežot taustiņu <xliff:g id="KEY">%1$s</xliff:g>, “<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>” tiek labots uz “<xliff:g id="CORRECTED">%3$s</xliff:g>”."</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Taustiņam <xliff:g id="KEY">%1$s</xliff:g> ir automātiskas labošanas funkcija."</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Taustiņu kods %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Pārslēgšanas taustiņš"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Pārslēgšanas taustiņš iespējots (pieskarieties, lai atspējotu)"</string>
diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml
index 3b039f120..5633cf8cf 100644
--- a/java/res/values-mn-rMN/strings.xml
+++ b/java/res/values-mn-rMN/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Нууц үгний товчнуудыг чангаар уншихыг сонсохын тулд чихэвчээ залгана уу."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Одоогийн текст %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст оруулаагүй"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>-г <xliff:g id="CORRECTED">%3$s</xliff:g> руу залруулна"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> автоматаар залруулна"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Товчийн код %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Сэлгэх"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Сэлгэхийг идэвхжүүлсэн (товшиж идэвхгүйжүүлнэ үү)"</string>
diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml
index ee241d64b..41bb9f80c 100644
--- a/java/res/values-ms-rMY/strings.xml
+++ b/java/res/values-ms-rMY/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Pasangkan set kepala untuk mendengar kekunci kata laluan disebut dengan kuat."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Teks semasa adalah %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Tiada teks dimasukkan"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> membetulkan <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> menjadi <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> melakukan auto pembetulan"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Kod kunci %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Kunci anjak dihidupkan (ketik untuk melumpuhkan)"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index ae43d1078..a473cce71 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Koble til hodetelefoner for å høre opplesing av bokstavene i passordet."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Gjeldende tekst er %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Ingen tekst er skrevet inn"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> retter <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> til <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> utfører automatisk retting"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Tastaturkode %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift er på (trykk for å deaktivere)"</string>
@@ -224,7 +222,7 @@
<string name="do_not_download_over_metered" msgid="2176209579313941583">"Last ned via Wi-Fi"</string>
<string name="dict_available_notification_title" msgid="6514288591959117288">"En ordliste er tilgjengelig for <xliff:g id="LANGUAGE">%1$s</xliff:g>"</string>
<string name="dict_available_notification_description" msgid="1075194169443163487">"Trykk for å se gjennom og laste ned"</string>
- <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Laster ned: forslag blir snart tilgjengelige for <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
+ <string name="toast_downloading_suggestions" msgid="1313027353588566660">"Laster ned: Forslag blir snart tilgjengelige for <xliff:g id="LANGUAGE">%1$s</xliff:g>."</string>
<string name="version_text" msgid="2715354215568469385">"Versjon <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
<string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Legg til"</string>
<string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Legg til i ordlisten"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index de20da4f8..60db9f0e8 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Sluit een headset aan om wachtwoordtoetsen hardop te laten voorlezen."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Huidige tekst is %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Geen tekst ingevoerd"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Met <xliff:g id="KEY">%1$s</xliff:g> wordt <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> gecorrigeerd naar <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Met <xliff:g id="KEY">%1$s</xliff:g> voert u automatische correctie uit"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Toetscode %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aan (tik om uit te schakelen)"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index 390837596..c3ed2d897 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Podłącz zestaw słuchawkowy, aby usłyszeć znaki hasła wypowiadane na głos."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Aktualny tekst: %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nie wprowadzono tekstu"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> poprawia <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> wykonuje autokorektę"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Kod klawisza: %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift włączony (kliknij, by wyłączyć)"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 4c81479e5..2a4c2b823 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Ligar auscultadores com microfone integrado para ouvir as teclas da palavra-passe."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"O texto atual é %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nenhum texto digitado"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> para <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> executa correção automática"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Código da tecla %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ativado (tocar para desativar)"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index ef533ae83..c0e1aa6b1 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Conecte um fone de ouvido para ouvir as chaves de senha em voz alta."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"O texto atual é %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nenhum texto digitado"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> para <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> realiza correção automática"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Código de tecla %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ativado (toque para desativar)"</string>
diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml
index c68d30c0c..b956619c5 100644
--- a/java/res/values-rm/strings.xml
+++ b/java/res/values-rm/strings.xml
@@ -139,9 +139,9 @@
<skip />
<!-- no translation found for spoken_no_text_entered (7479685225597344496) -->
<skip />
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
+ <!-- no translation found for spoken_auto_correct (8005997889020109763) -->
<skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
+ <!-- no translation found for spoken_auto_correct_obscured (6276420476908833791) -->
<skip />
<!-- no translation found for spoken_description_unknown (3197434010402179157) -->
<skip />
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 930b68bd6..c24ec01d1 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Conectaţi un set căşti-microfon pentru a auzi tastele apăsate când introduceţi parola."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Textul curent este %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nu a fost introdus text"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> corectează <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> cu <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> efectuează corectare automată"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Tasta cu codul %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Tasta Shift este activată (apăsaţi pentru a o dezactiva)"</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index 8bfb011c5..176e75eda 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Подключите гарнитуру, чтобы услышать пароль."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Введенный текст: %s."</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст не введен"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"При нажатии клавиши \"<xliff:g id="KEY">%1$s</xliff:g>\" слово \"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>\" будет исправлено на \"<xliff:g id="CORRECTED">%3$s</xliff:g>\""</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Для клавиши \"<xliff:g id="KEY">%1$s</xliff:g>\" назначена функция автоисправления"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Код клавиши:%d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Клавиша верхнего регистра"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Верхний регистр включен (нажмите, чтобы отключить)"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 5c25f28ce..bc5d6d297 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Ak si chcete pri zadávaní hesla vypočuť nahlas vyslovené klávesy, pripojte náhlavnú súpravu."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Aktuálny text je %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Nie je zadaný žiadny text"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Klávesom <xliff:g id="KEY">%1$s</xliff:g> opravíte slovo <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Klávesom <xliff:g id="KEY">%1$s</xliff:g> spustíte automatické opravy"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Kód klávesu %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Kláves Shift je zapnutý (zakážete ho klepnutím)"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index dde01dd68..c7d698b2f 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Priključite slušalke, če želite slišati izgovorjene tipke gesla."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Trenutno besedilo je %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Ni vnesenega besedila"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Tipka <xliff:g id="KEY">%1$s</xliff:g> popravi <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> v <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Tipka <xliff:g id="KEY">%1$s</xliff:g> izvede samodejno popravljanje"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Koda tipke %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift je vklopljen (dotaknite se, da onemogočite)"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index e7f6904c1..e93661a93 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Укључите слушалице да бисте чули наглас изговорене тастере за лозинку."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Тренутни текст је %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст није унет"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> исправља <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> у <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> обавља функцију аутоматског исправљања"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Кôд тастера %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift је укључен (додирните да бисте га онемогућили)"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 0fcca4837..1b23e334e 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Anslut hörlurar om du vill att lösenordet ska läsas upp."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Nuvarande text är %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Ingen text har angetts"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Om du trycker på <xliff:g id="KEY">%1$s</xliff:g> rättas <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> till <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Om du trycker på <xliff:g id="KEY">%1$s</xliff:g> utförs autokorrigering"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Nyckelkod %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Skift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Skift på (knacka lätt för att inaktivera)"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index fbf868f24..9a22d20c5 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Chomeka plagi ya kifaa cha kichwa cha kusikiza ili kusikiliza msimbo wa nenosiri inayozungumwa kwa sauti ya juu."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Maandishi ya sasa ni %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Hakuna maandishi yaliyoingizwa"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> hurekebisha <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> kuwa <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> hurekebisha kiotomatiki"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Msimbo wa kitufe %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Badilisha"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift imewashwa (gonga ili kulemaza)"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index f84b32c62..bb8b556ce 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"เสียบชุดหูฟังเพื่อฟังเสียงเมื่อพิมพ์รหัสผ่าน"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"ข้อความปัจจุบันคือ %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"ไม่มีข้อความ"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> แก้ไข <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> เป็น <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> ทำการแก้ไขอัตโนมัติ"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"รหัสคีย์ %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift เปิดอยู่ (แตะเพื่อปิดใช้งาน)"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index af1c68e01..60ba0814c 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Mag-plug in ng headset upang marinig ang mga password key na binabanggit nang malakas."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Ang kasalukuyang teksto ay %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Walang tekstong inilagay"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"Itatama at gagawing <xliff:g id="CORRECTED">%3$s</xliff:g> ng <xliff:g id="KEY">%1$s</xliff:g> ang <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"Magsasagawa ng auto-correction ang <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Code ng key %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Naka-on ang shift (i-tap upang huwag paganahin)"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index 4c8e1a81d..676cc3c7d 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Şifre tuşlarının sesli okunmasını dinlemek için mikrofonlu kulaklık takın."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Mevcut metin: %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Hiç metin girilmedi"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> tuşu <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> kelimesini <xliff:g id="CORRECTED">%3$s</xliff:g> olarak düzeltir"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> tuşu otomatik düzeltme gerçekleştirir"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Tuş kodu: %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Üst Karakter"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Üst karakter açık (devre dışı bırakmak için hafifçe vurun)"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index 287bcb397..2a8b937c2 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Підключіть гарнітуру, щоб прослухати відтворені вголос символи пароля."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Поточний текст – %s."</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст не введено"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> виправляє <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> на <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> здійснює автоматичне виправлення"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Код клавіші – %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Клавіша Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift увімкнено (швидко торкніться, щоб вимкнути)"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index 8764df5e0..74ef95a83 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Cắm tai nghe để nghe mật khẩu."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Ký tự hiện tại là %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Không có ký tự nào được nhập"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"<xliff:g id="KEY">%1$s</xliff:g> sửa <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> thành <xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"<xliff:g id="KEY">%1$s</xliff:g> thực hiện tự động sửa"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Mã phím %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift đang bật (bấm để tắt)"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index f7ceff44f..c55269329 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"需要插入耳机才能听到密码的按键声。"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"当前文本为%s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"未输入文字"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"按<xliff:g id="KEY">%1$s</xliff:g>可将<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>更正为<xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"按<xliff:g id="KEY">%1$s</xliff:g>可执行自动更正"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"键码为 %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift 模式已启用(点按即可停用)"</string>
diff --git a/java/res/values-zh-rHK/strings-appname.xml b/java/res/values-zh-rHK/strings-appname.xml
new file mode 100644
index 000000000..8761a98d0
--- /dev/null
+++ b/java/res/values-zh-rHK/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_name" msgid="5940510615957428904">"Android 鍵盤 (AOSP)"</string>
+ <string name="spell_checker_service_name" msgid="1254221805440242662">"Android 拼字檢查工具 (AOSP)"</string>
+ <string name="english_ime_settings" msgid="5760361067176802794">"Android 鍵盤設定 (AOSP)"</string>
+ <string name="android_spell_checker_settings" msgid="6123949487832861885">"Android 拼字檢查工具設定 (AOSP)"</string>
+</resources>
diff --git a/java/res/values-zh-rHK/strings.xml b/java/res/values-zh-rHK/strings.xml
new file mode 100644
index 000000000..1d4f36a62
--- /dev/null
+++ b/java/res/values-zh-rHK/strings.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string>
+ <string name="english_ime_research_log" msgid="8492602295696577851">"研究記錄指令"</string>
+ <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查找聯絡人姓名"</string>
+ <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼字檢查程式使用您的聯絡人名單中的各項記錄"</string>
+ <string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string>
+ <string name="sound_on_keypress" msgid="6093592297198243644">"按鍵時播放音效"</string>
+ <string name="popup_on_keypress" msgid="123894815723512944">"按鍵時顯示彈出式視窗"</string>
+ <string name="general_category" msgid="1859088467017573195">"一般設定"</string>
+ <string name="correction_category" msgid="2236750915056607613">"文字更正"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"手勢輸入"</string>
+ <string name="misc_category" msgid="6894192814868233453">"其他選項"</string>
+ <string name="advanced_settings" msgid="362895144495591463">"進階設定"</string>
+ <string name="advanced_settings_summary" msgid="4487980456152830271">"專家選項"</string>
+ <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"切換至其他輸入法"</string>
+ <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"語言切換鍵包括其他輸入法"</string>
+ <string name="show_language_switch_key" msgid="5915478828318774384">"語言切換鍵"</string>
+ <string name="show_language_switch_key_summary" msgid="7343403647474265713">"在啟用多種輸入語言時顯示"</string>
+ <string name="sliding_key_input_preview" msgid="6604262359510068370">"顯示滑動指示器"</string>
+ <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"從 Shift 鍵或符號鍵開始滑動時顯示視覺提示"</string>
+ <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"關閉彈出式鍵盤的延遲時間"</string>
+ <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"不延遲"</string>
+ <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"預設"</string>
+ <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> 毫秒"</string>
+ <string name="settings_system_default" msgid="6268225104743331821">"系統預設"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"建議聯絡人名稱"</string>
+ <string name="use_contacts_dict_summary" msgid="6599983334507879959">"使用「聯絡人」的名稱提供建議與修正"</string>
+ <string name="use_double_space_period" msgid="8781529969425082860">"按兩下空格鍵插入句號"</string>
+ <string name="use_double_space_period_summary" msgid="6532892187247952799">"只要輕按兩下空格鍵,即可插入句號並在後面加上一個空格"</string>
+ <string name="auto_cap" msgid="1719746674854628252">"自動大寫"</string>
+ <string name="auto_cap_summary" msgid="7934452761022946874">"每句首個字詞大寫"</string>
+ <string name="edit_personal_dictionary" msgid="3996910038952940420">"個人字典"</string>
+ <string name="configure_dictionaries_title" msgid="4238652338556902049">"附加字典"</string>
+ <string name="main_dictionary" msgid="4798763781818361168">"主要字典"</string>
+ <string name="prefs_show_suggestions" msgid="8026799663445531637">"顯示更正建議"</string>
+ <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"輸入時顯示建議字詞"</string>
+ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"永遠顯示"</string>
+ <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"以垂直模式顯示"</string>
+ <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"永遠隱藏"</string>
+ <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"封鎖令人反感的字詞"</string>
+ <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"不建議使用可能令人反感的字詞"</string>
+ <string name="auto_correction" msgid="7630720885194996950">"自動更正"</string>
+ <string name="auto_correction_summary" msgid="5625751551134658006">"自動插入空白鍵和標點符號鍵盤,以修正拼字錯誤"</string>
+ <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"關閉"</string>
+ <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"普通模式"</string>
+ <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"加強模式"</string>
+ <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"極度加強模式"</string>
+ <string name="bigram_prediction" msgid="1084449187723948550">"建議下一個字詞"</string>
+ <string name="bigram_prediction_summary" msgid="3896362682751109677">"根據前一個字詞提出建議"</string>
+ <string name="gesture_input" msgid="826951152254563827">"啟用手勢輸入"</string>
+ <string name="gesture_input_summary" msgid="9180350639305731231">"透過滑動手指寫出字母來輸入字詞"</string>
+ <string name="gesture_preview_trail" msgid="3802333369335722221">"顯示手勢軌跡"</string>
+ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"動態浮動預覽"</string>
+ <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"在啟用手勢輸入時顯示建議的字詞"</string>
+ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已儲存"</string>
+ <string name="label_go_key" msgid="1635148082137219148">"開始"</string>
+ <string name="label_next_key" msgid="362972844525672568">"下一步"</string>
+ <string name="label_previous_key" msgid="1211868118071386787">"上一步"</string>
+ <string name="label_done_key" msgid="2441578748772529288">"完成"</string>
+ <string name="label_send_key" msgid="2815056534433717444">"發送"</string>
+ <string name="label_pause_key" msgid="181098308428035340">"暫停"</string>
+ <string name="label_wait_key" msgid="6402152600878093134">"等候"</string>
+ <string name="spoken_use_headphones" msgid="896961781287283493">"插上耳機即可聽到系統朗讀密碼鍵。"</string>
+ <string name="spoken_current_text_is" msgid="2485723011272583845">"目前文字為 %s"</string>
+ <string name="spoken_no_text_entered" msgid="7479685225597344496">"未輸入文字"</string>
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"按「<xliff:g id="KEY">%1$s</xliff:g>」可將「<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>」修正為「<xliff:g id="CORRECTED">%3$s</xliff:g>」"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"按「<xliff:g id="KEY">%1$s</xliff:g>」可自動修正"</string>
+ <string name="spoken_description_unknown" msgid="3197434010402179157">"按鍵代碼 %d"</string>
+ <string name="spoken_description_shift" msgid="244197883292549308">"Shift 鍵"</string>
+ <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift 鍵已開啟 (輕按即可停用)"</string>
+ <string name="spoken_description_caps_lock" msgid="3276478269526304432">"大寫鎖定已開啟 (輕按即可停用)"</string>
+ <string name="spoken_description_delete" msgid="8740376944276199801">"刪除"</string>
+ <string name="spoken_description_to_symbol" msgid="5486340107500448969">"符號"</string>
+ <string name="spoken_description_to_alpha" msgid="23129338819771807">"字母"</string>
+ <string name="spoken_description_to_numeric" msgid="591752092685161732">"數字"</string>
+ <string name="spoken_description_settings" msgid="4627462689603838099">"設定"</string>
+ <string name="spoken_description_tab" msgid="2667716002663482248">"Tab 鍵"</string>
+ <string name="spoken_description_space" msgid="2582521050049860859">"空白鍵"</string>
+ <string name="spoken_description_mic" msgid="615536748882611950">"語音輸入"</string>
+ <string name="spoken_description_smiley" msgid="2256309826200113918">"笑臉"</string>
+ <string name="spoken_description_return" msgid="8178083177238315647">"Return 鍵"</string>
+ <string name="spoken_description_search" msgid="1247236163755920808">"搜尋"</string>
+ <string name="spoken_description_dot" msgid="40711082435231673">"點"</string>
+ <string name="spoken_description_language_switch" msgid="5507091328222331316">"切換語言"</string>
+ <string name="spoken_description_action_next" msgid="8636078276664150324">"下一步"</string>
+ <string name="spoken_description_action_previous" msgid="800872415009336208">"上一步"</string>
+ <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 鍵已啟用"</string>
+ <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"大寫鎖定已啟用"</string>
+ <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift 鍵已停用"</string>
+ <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"符號模式"</string>
+ <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"字母模式"</string>
+ <string name="spoken_description_mode_phone" msgid="6520207943132026264">"撥號模式"</string>
+ <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"符號撥號模式"</string>
+ <string name="announce_keyboard_hidden" msgid="8718927835531429807">"鍵盤已隱藏"</string>
+ <string name="announce_keyboard_mode" msgid="4729081055438508321">"目前顯示的是<xliff:g id="MODE">%s</xliff:g>鍵盤"</string>
+ <string name="keyboard_mode_date" msgid="3137520166817128102">"日期"</string>
+ <string name="keyboard_mode_date_time" msgid="339593358488851072">"日期和時間"</string>
+ <string name="keyboard_mode_email" msgid="6216248078128294262">"電郵"</string>
+ <string name="keyboard_mode_im" msgid="1137405089766557048">"短訊"</string>
+ <string name="keyboard_mode_number" msgid="7991623440699957069">"數字"</string>
+ <string name="keyboard_mode_phone" msgid="6851627527401433229">"電話"</string>
+ <string name="keyboard_mode_text" msgid="6479436687899701619">"文字"</string>
+ <string name="keyboard_mode_time" msgid="4381856885582143277">"時間"</string>
+ <string name="keyboard_mode_url" msgid="1519819835514911218">"網址"</string>
+ <string name="voice_input" msgid="3583258583521397548">"語音輸入鍵"</string>
+ <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"於主鍵盤"</string>
+ <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"符號鍵盤上"</string>
+ <string name="voice_input_modes_off" msgid="3745699748218082014">"關閉"</string>
+ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"主鍵盤上的麥克風"</string>
+ <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"符號鍵盤上的麥克風"</string>
+ <string name="voice_input_modes_summary_off" msgid="63875609591897607">"語音輸入已停用"</string>
+ <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string>
+ <string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string>
+ <string name="send_feedback" msgid="1780431884109392046">"傳送意見"</string>
+ <string name="select_language" msgid="3693815588777926848">"輸入語言"</string>
+ <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次輕觸即可儲存"</string>
+ <string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string>
+ <string name="prefs_enable_log" msgid="6620424505072963557">"啟用用戶意見反映"</string>
+ <string name="prefs_description_log" msgid="7525225584555429211">"自動傳送使用統計資料和當機報告,協助改良這個輸入法編輯器"</string>
+ <string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string>
+ <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英國)"</string>
+ <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美國)"</string>
+ <string name="subtype_es_US" msgid="5583145191430180200">"西班牙文 (美國)"</string>
+ <string name="subtype_with_layout_en_GB" msgid="2179097748724725906">"英文 (英國) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_en_US" msgid="1362581347576714579">"英文 (美國) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_with_layout_es_US" msgid="6261791057007890189">"西班牙文 (美國) (<xliff:g id="LAYOUT">%s</xliff:g>)"</string>
+ <string name="subtype_nepali_traditional" msgid="9032247506728040447">"<xliff:g id="LANGUAGE">%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>
+ <string name="subtype_no_language_azerty" msgid="8144348527575640087">"字母 (AZERTY)"</string>
+ <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"字母 (Dvorak)"</string>
+ <string name="subtype_no_language_colemak" msgid="5837418400010302623">"字母 (Colemak)"</string>
+ <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"字母 (PC)"</string>
+ <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
+ <string name="custom_input_styles_title" msgid="8429952441821251512">"自訂輸入樣式"</string>
+ <string name="add_style" msgid="6163126614514489951">"新增樣式"</string>
+ <string name="add" msgid="8299699805688017798">"新增"</string>
+ <string name="remove" msgid="4486081658752944606">"移除"</string>
+ <string name="save" msgid="7646738597196767214">"儲存"</string>
+ <string name="subtype_locale" msgid="8576443440738143764">"語言"</string>
+ <string name="keyboard_layout_set" msgid="4309233698194565609">"配置"</string>
+ <string name="custom_input_style_note_message" msgid="8826731320846363423">"您必須先啟用自訂輸入樣式,才能開始使用。您要立即啟用嗎?"</string>
+ <string name="enable" msgid="5031294444630523247">"啟用"</string>
+ <string name="not_now" msgid="6172462888202790482">"暫時不要"</string>
+ <string name="custom_input_style_already_exists" msgid="8008728952215449707">"已存在相同的輸入樣式:<xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+ <string name="prefs_usability_study_mode" msgid="1261130555134595254">"可用性研究模式"</string>
+ <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"長按鍵延遲"</string>
+ <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"按鍵震動時間"</string>
+ <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"按鍵音量"</string>
+ <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"讀取外部字典檔案"</string>
+ <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"「下載」資料夾中沒有任何字典檔案"</string>
+ <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"選取要安裝的字典檔案"</string>
+ <string name="read_external_dictionary_confirm_install_message" msgid="6898610163768980870">"準備好要為<xliff:g id="LOCALE_NAME">%s</xliff:g>版本安裝這個檔案嗎?"</string>
+ <string name="error" msgid="8940763624668513648">"發生錯誤"</string>
+ <string name="button_default" msgid="3988017840431881491">"預設"</string>
+ <string name="setup_welcome_title" msgid="6112821709832031715">"歡迎使用「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」"</string>
+ <string name="setup_welcome_additional_description" msgid="8150252008545768953">"配備觸控輸入功能"</string>
+ <string name="setup_start_action" msgid="8936036460897347708">"開始"</string>
+ <string name="setup_next_action" msgid="371821437915144603">"下一步"</string>
+ <string name="setup_steps_title" msgid="6400373034871816182">"設定「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」"</string>
+ <string name="setup_step1_title" msgid="3147967630253462315">"啟用「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」"</string>
+ <string name="setup_step1_instruction" msgid="2578631936624637241">"請在語言與輸入設定中勾選「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」,授權這個應用程式在您的裝置上執行。"</string>
+ <string name="setup_step1_finished_instruction" msgid="10761482004957994">"您已在 [語言與輸入設定] 中啟用「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」。這個步驟已完成,可繼續下一個步驟了!"</string>
+ <string name="setup_step1_action" msgid="4366513534999901728">"在設定中啟用"</string>
+ <string name="setup_step2_title" msgid="6860725447906690594">"切換至「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」"</string>
+ <string name="setup_step2_instruction" msgid="9141481964870023336">"接著,請選取「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」作為目前使用的文字輸入方法。"</string>
+ <string name="setup_step2_action" msgid="1660330307159824337">"切換輸入方法"</string>
+ <string name="setup_step3_title" msgid="3154757183631490281">"恭喜,一切就緒!"</string>
+ <string name="setup_step3_instruction" msgid="8025981829605426000">"現在,您可以在所有最愛的應用程式中使用「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」輸入文字。"</string>
+ <string name="setup_step3_action" msgid="600879797256942259">"設定其他語言"</string>
+ <string name="setup_finish_action" msgid="276559243409465389">"完成"</string>
+ <string name="show_setup_wizard_icon" msgid="5008028590593710830">"顯示應用程式圖示"</string>
+ <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"在啟動器中顯示應用程式圖示"</string>
+ <string name="app_name" msgid="6320102637491234792">"字典供應商"</string>
+ <string name="dictionary_provider_name" msgid="3027315045397363079">"字典供應商"</string>
+ <string name="dictionary_service_name" msgid="6237472350693511448">"字典服務"</string>
+ <string name="download_description" msgid="6014835283119198591">"字典更新資訊"</string>
+ <string name="dictionary_settings_title" msgid="8091417676045693313">"附加字典"</string>
+ <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"可使用字典"</string>
+ <string name="dictionary_settings_summary" msgid="5305694987799824349">"字典設定"</string>
+ <string name="user_dictionaries" msgid="3582332055892252845">"用戶字典"</string>
+ <string name="default_user_dict_pref_name" msgid="1625055720489280530">"用戶字典"</string>
+ <string name="dictionary_available" msgid="4728975345815214218">"可使用字典"</string>
+ <string name="dictionary_downloading" msgid="2982650524622620983">"目前下載中"</string>
+ <string name="dictionary_installed" msgid="8081558343559342962">"已安裝"</string>
+ <string name="dictionary_disabled" msgid="8950383219564621762">"已安裝,但已停用"</string>
+ <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"連線至字典服務時發生問題"</string>
+ <string name="no_dictionaries_available" msgid="8039920716566132611">"沒有可用的字典"</string>
+ <string name="check_for_updates_now" msgid="8087688440916388581">"重新整理"</string>
+ <string name="last_update" msgid="730467549913588780">"上次更新日期"</string>
+ <string name="message_updating" msgid="4457761393932375219">"正在查看更新"</string>
+ <string name="message_loading" msgid="8689096636874758814">"正在載入..."</string>
+ <string name="main_dict_description" msgid="3072821352793492143">"主要字典"</string>
+ <string name="cancel" msgid="6830980399865683324">"取消"</string>
+ <string name="install_dict" msgid="180852772562189365">"安裝"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"取消"</string>
+ <string name="delete_dict" msgid="756853268088330054">"刪除"</string>
+ <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"您的流動裝置所選取的語言現有字典可供使用。&lt;br/&gt;建議您&lt;b&gt;下載&lt;/b&gt;<xliff:g id="LANGUAGE">%1$s</xliff:g>字典,讓您輸入時更方便。&lt;br/&gt;&lt;br/&gt;經由 3G 網絡下載需時一兩分鐘。如果您未使用&lt;b&gt;無限上網計劃&lt;/b&gt;,可能須另外付費。&lt;br/&gt;如果您不確定自己使用哪種上網計劃,建議您在連接 Wi-Fi 網絡後才開始自動下載。&lt;br/&gt;&lt;br/&gt;提示:您可以前往流動裝置的 [設定] &lt;b&gt;&lt;/b&gt;選單,透過其中的 [語言和輸入] &lt;b&gt;&lt;/b&gt;下載和移除字典。"</string>
+ <string name="download_over_metered" msgid="1643065851159409546">"立即下載 (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+ <string name="do_not_download_over_metered" msgid="2176209579313941583">"經由 Wi-Fi 下載"</string>
+ <string name="dict_available_notification_title" msgid="6514288591959117288">"可使用<xliff:g id="LANGUAGE">%1$s</xliff:g>字典"</string>
+ <string name="dict_available_notification_description" msgid="1075194169443163487">"按下即可查看並下載"</string>
+ <string name="toast_downloading_suggestions" msgid="1313027353588566660">"下載中:很快就能提供<xliff:g id="LANGUAGE">%1$s</xliff:g>字詞建議。"</string>
+ <string name="version_text" msgid="2715354215568469385">"版本 <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+ <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"新增"</string>
+ <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"加入字典"</string>
+ <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"詞組"</string>
+ <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"更多選項"</string>
+ <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"較少選項"</string>
+ <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"確定"</string>
+ <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"字詞:"</string>
+ <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"快速鍵:"</string>
+ <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"語言:"</string>
+ <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"輸入字詞"</string>
+ <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"自選快速鍵"</string>
+ <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"編輯字詞"</string>
+ <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"編輯"</string>
+ <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"刪除"</string>
+ <string name="user_dict_settings_empty_text" msgid="558499587532668203">"您的用戶字典中沒有任何字詞。輕觸 [新增] (+) 按鈕即可新增字詞。"</string>
+ <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"所有語言"</string>
+ <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"更多語言..."</string>
+ <string name="user_dict_settings_delete" msgid="110413335187193859">"刪除"</string>
+ <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+</resources>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index b773ad21c..4d39050f7 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -29,7 +29,7 @@
<string name="popup_on_keypress" msgid="123894815723512944">"按鍵時彈出"</string>
<string name="general_category" msgid="1859088467017573195">"一般"</string>
<string name="correction_category" msgid="2236750915056607613">"文字修正"</string>
- <string name="gesture_typing_category" msgid="497263612130532630">"手勢輸入"</string>
+ <string name="gesture_typing_category" msgid="497263612130532630">"滑行輸入"</string>
<string name="misc_category" msgid="6894192814868233453">"其他選項"</string>
<string name="advanced_settings" msgid="362895144495591463">"進階設定"</string>
<string name="advanced_settings_summary" msgid="4487980456152830271">"進階選項"</string>
@@ -44,7 +44,7 @@
<string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"預設"</string>
<string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> 毫秒"</string>
<string name="settings_system_default" msgid="6268225104743331821">"系統預設"</string>
- <string name="use_contacts_dict" msgid="4435317977804180815">"建議聯絡人姓名"</string>
+ <string name="use_contacts_dict" msgid="4435317977804180815">"聯絡人姓名建議"</string>
<string name="use_contacts_dict_summary" msgid="6599983334507879959">"根據「聯絡人」名稱提供建議與修正"</string>
<string name="use_double_space_period" msgid="8781529969425082860">"輕按兩下空格鍵即插入句號"</string>
<string name="use_double_space_period_summary" msgid="6532892187247952799">"輕按兩下空格鍵可插入句號另加一個空格"</string>
@@ -68,11 +68,11 @@
<string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"極大幅度更正"</string>
<string name="bigram_prediction" msgid="1084449187723948550">"建議下一個字詞"</string>
<string name="bigram_prediction_summary" msgid="3896362682751109677">"根據前一個字詞提供建議"</string>
- <string name="gesture_input" msgid="826951152254563827">"啟用手勢輸入"</string>
+ <string name="gesture_input" msgid="826951152254563827">"啟用滑行輸入"</string>
<string name="gesture_input_summary" msgid="9180350639305731231">"以滑動方式寫出字詞中字母來輸入字詞"</string>
<string name="gesture_preview_trail" msgid="3802333369335722221">"顯示手勢軌跡"</string>
<string name="gesture_floating_preview_text" msgid="4443240334739381053">"動態浮動預覽"</string>
- <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"使用手勢輸入時顯示建議字詞"</string>
+ <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"使用滑行輸入時顯示建議字詞"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已儲存"</string>
<string name="label_go_key" msgid="1635148082137219148">"前往"</string>
<string name="label_next_key" msgid="362972844525672568">"下一頁"</string>
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"連接耳機即可聽取系統朗讀密碼按鍵。"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"目前文字為 %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"未輸入文字"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"按下「<xliff:g id="KEY">%1$s</xliff:g>」可將「<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>」修正為「<xliff:g id="CORRECTED">%3$s</xliff:g>」"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"按下「<xliff:g id="KEY">%1$s</xliff:g>」可執行自動修正"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"按鍵代碼 %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift 鍵"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift 鍵已開啟 (輕按即可停用)"</string>
@@ -178,7 +176,7 @@
<string name="error" msgid="8940763624668513648">"發生錯誤"</string>
<string name="button_default" msgid="3988017840431881491">"預設"</string>
<string name="setup_welcome_title" msgid="6112821709832031715">"歡迎使用 <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
- <string name="setup_welcome_additional_description" msgid="8150252008545768953">"含手勢輸入功能"</string>
+ <string name="setup_welcome_additional_description" msgid="8150252008545768953">"含滑行輸入功能"</string>
<string name="setup_start_action" msgid="8936036460897347708">"開始設定"</string>
<string name="setup_next_action" msgid="371821437915144603">"下一步"</string>
<string name="setup_steps_title" msgid="6400373034871816182">"正在設定「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index 8f722cce3..d245c32d4 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -84,10 +84,8 @@
<string name="spoken_use_headphones" msgid="896961781287283493">"Plaka ku-headset ukuze uzwe okhiye bephasiwedi ezindlebeni zakho bezwakala kakhulu."</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"Umbhalo wamanje ngu %s"</string>
<string name="spoken_no_text_entered" msgid="7479685225597344496">"Awukho umbhalo ofakiwe"</string>
- <!-- no translation found for spoken_auto_correct (5381764628886369268) -->
- <skip />
- <!-- no translation found for spoken_auto_correct_obscured (1186884531440481089) -->
- <skip />
+ <string name="spoken_auto_correct" msgid="8005997889020109763">"I-<xliff:g id="KEY">%1$s</xliff:g> ilungisa i-<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ibe yi-<xliff:g id="CORRECTED">%3$s</xliff:g>"</string>
+ <string name="spoken_auto_correct_obscured" msgid="6276420476908833791">"I-<xliff:g id="KEY">%1$s</xliff:g> yenza ukulungiswa kokuzenzakalela"</string>
<string name="spoken_description_unknown" msgid="3197434010402179157">"Ikhodi yokhiye %d"</string>
<string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string>
<string name="spoken_description_shift_shifted" msgid="1681877323344195035">"U-Shift uvuliwe (thepha ukuwuvimbela)"</string>
diff --git a/java/res/xml-sw600dp/rows_swiss.xml b/java/res/xml-sw600dp/rows_swiss.xml
new file mode 100644
index 000000000..4f4ca85b4
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_swiss.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_swiss1" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_swiss2" />
+ <Key
+ latin:keyStyle="enterKeyStyle"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <Row
+ latin:keyWidth="8.182%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="10.0%p" />
+ <Spacer
+ latin:keyWidth="3.181%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz3" />
+ <include
+ latin:keyboardLayout="@xml/keys_exclamation_question" />
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyXPos="-10.0%p"
+ latin:keyWidth="fillRight" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/kbd_swiss.xml b/java/res/xml/kbd_swiss.xml
new file mode 100644
index 000000000..c64ad1103
--- /dev/null
+++ b/java/res/xml/kbd_swiss.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rows_swiss" />
+</Keyboard>
diff --git a/java/res/xml/keyboard_layout_set_swiss.xml b/java/res/xml/keyboard_layout_set_swiss.xml
new file mode 100644
index 000000000..e17a5ab8b
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_swiss.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<KeyboardLayoutSet
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+ <Element
+ latin:elementName="alphabet"
+ latin:elementKeyboard="@xml/kbd_swiss"
+ latin:enableProximityCharsCorrection="true" />
+ <Element
+ latin:elementName="symbols"
+ latin:elementKeyboard="@xml/kbd_symbols" />
+ <Element
+ latin:elementName="symbolsShifted"
+ latin:elementKeyboard="@xml/kbd_symbols_shift" />
+ <Element
+ latin:elementName="phone"
+ latin:elementKeyboard="@xml/kbd_phone" />
+ <Element
+ latin:elementName="phoneSymbols"
+ latin:elementKeyboard="@xml/kbd_phone_symbols" />
+ <Element
+ latin:elementName="number"
+ latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardLayoutSet>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 0a27da93f..8a84a4c57 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -32,6 +32,7 @@
cs: Czech/qwertz
da: Danish/nordic
de: German/qwertz
+ de_CH: German Switzerland/swiss
el: Greek/greek
en_US: English United States/qwerty
en_GB: English Great Britain/qwerty
@@ -44,6 +45,7 @@
fi: Finnish/nordic
fr: French/azerty
fr_CA: French Canada/qwerty
+ fr_CH: French Switzerland/swiss
hi: Hindi/hindi
hr: Croatian/qwertz
hu: Hungarian/qwertz
@@ -183,6 +185,13 @@
/>
<subtype android:icon="@drawable/ic_ime_switcher_dark"
android:label="@string/subtype_generic"
+ android:subtypeId="0x7acfd0aa"
+ android:imeSubtypeLocale="de_CH"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=swiss,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable"
+ />
+ <subtype android:icon="@drawable/ic_ime_switcher_dark"
+ android:label="@string/subtype_generic"
android:subtypeId="0x0e7802d3"
android:imeSubtypeLocale="el"
android:imeSubtypeMode="keyboard"
@@ -255,6 +264,13 @@
/>
<subtype android:icon="@drawable/ic_ime_switcher_dark"
android:label="@string/subtype_generic"
+ android:subtypeId="0xeadc55f5"
+ android:imeSubtypeLocale="fr_CH"
+ android:imeSubtypeMode="keyboard"
+ android:imeSubtypeExtraValue="KeyboardLayoutSet=swiss,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable"
+ />
+ <subtype android:icon="@drawable/ic_ime_switcher_dark"
+ android:label="@string/subtype_generic"
android:subtypeId="0x39753b7f"
android:imeSubtypeLocale="hi"
android:imeSubtypeMode="keyboard"
diff --git a/java/res/xml/rowkeys_swiss1.xml b/java/res/xml/rowkeys_swiss1.xml
new file mode 100644
index 000000000..e3b842619
--- /dev/null
+++ b/java/res/xml/rowkeys_swiss1.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz1" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_swiss_row1_11"
+ latin:moreKeys="!text/more_keys_for_swiss_row1_11" />
+</merge>
diff --git a/java/res/xml/rowkeys_swiss2.xml b/java/res/xml/rowkeys_swiss2.xml
new file mode 100644
index 000000000..5364a448c
--- /dev/null
+++ b/java/res/xml/rowkeys_swiss2.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_swiss_row2_10"
+ latin:moreKeys="!text/more_keys_for_swiss_row2_10" />
+ <Key
+ latin:keyLabel="!text/keylabel_for_swiss_row2_11"
+ latin:moreKeys="!text/more_keys_for_swiss_row2_11" />
+</merge>
diff --git a/java/res/xml/rows_swiss.xml b/java/res/xml/rows_swiss.xml
new file mode 100644
index 000000000..03e412940
--- /dev/null
+++ b/java/res/xml/rows_swiss.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+ <include
+ latin:keyboardLayout="@xml/key_styles_common" />
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_swiss1" />
+ </Row>
+ <Row
+ latin:keyWidth="9.091%p"
+ >
+ <include
+ latin:keyboardLayout="@xml/rowkeys_swiss2" />
+ </Row>
+ <Row
+ latin:keyWidth="9.2%p"
+ >
+ <Key
+ latin:keyStyle="shiftKeyStyle"
+ latin:keyWidth="15%p"
+ latin:visualInsetsRight="1%p" />
+ <Spacer
+ latin:keyWidth="2.8%p" />
+ <include
+ latin:keyboardLayout="@xml/rowkeys_qwertz3" />
+ <Key
+ latin:keyStyle="deleteKeyStyle"
+ latin:keyXPos="-15%p"
+ latin:keyWidth="fillRight"
+ latin:visualInsetsLeft="1%p" />
+ </Row>
+ <include
+ latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index e769e3cdd..98515c893 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -147,111 +147,117 @@ public final class KeyboardTextsSet {
/* 42 */ "keylabel_for_south_slavic_row3_8",
/* 43 */ "more_keys_for_cyrillic_ie",
/* 44 */ "more_keys_for_cyrillic_i",
- /* 45 */ "label_to_alpha_key",
- /* 46 */ "single_quotes",
- /* 47 */ "double_quotes",
- /* 48 */ "single_angle_quotes",
- /* 49 */ "double_angle_quotes",
- /* 50 */ "more_keys_for_currency_dollar",
- /* 51 */ "keylabel_for_currency",
- /* 52 */ "more_keys_for_currency",
- /* 53 */ "more_keys_for_punctuation",
- /* 54 */ "more_keys_for_star",
- /* 55 */ "more_keys_for_bullet",
- /* 56 */ "more_keys_for_plus",
- /* 57 */ "more_keys_for_left_parenthesis",
- /* 58 */ "more_keys_for_right_parenthesis",
- /* 59 */ "more_keys_for_less_than",
- /* 60 */ "more_keys_for_greater_than",
- /* 61 */ "more_keys_for_arabic_diacritics",
- /* 62 */ "keyhintlabel_for_arabic_diacritics",
- /* 63 */ "keylabel_for_symbols_1",
- /* 64 */ "keylabel_for_symbols_2",
- /* 65 */ "keylabel_for_symbols_3",
- /* 66 */ "keylabel_for_symbols_4",
- /* 67 */ "keylabel_for_symbols_5",
- /* 68 */ "keylabel_for_symbols_6",
- /* 69 */ "keylabel_for_symbols_7",
- /* 70 */ "keylabel_for_symbols_8",
- /* 71 */ "keylabel_for_symbols_9",
- /* 72 */ "keylabel_for_symbols_0",
- /* 73 */ "label_to_symbol_key",
- /* 74 */ "label_to_symbol_with_microphone_key",
- /* 75 */ "additional_more_keys_for_symbols_1",
- /* 76 */ "additional_more_keys_for_symbols_2",
- /* 77 */ "additional_more_keys_for_symbols_3",
- /* 78 */ "additional_more_keys_for_symbols_4",
- /* 79 */ "additional_more_keys_for_symbols_5",
- /* 80 */ "additional_more_keys_for_symbols_6",
- /* 81 */ "additional_more_keys_for_symbols_7",
- /* 82 */ "additional_more_keys_for_symbols_8",
- /* 83 */ "additional_more_keys_for_symbols_9",
- /* 84 */ "additional_more_keys_for_symbols_0",
- /* 85 */ "more_keys_for_symbols_1",
- /* 86 */ "more_keys_for_symbols_2",
- /* 87 */ "more_keys_for_symbols_3",
- /* 88 */ "more_keys_for_symbols_4",
- /* 89 */ "more_keys_for_symbols_5",
- /* 90 */ "more_keys_for_symbols_6",
- /* 91 */ "more_keys_for_symbols_7",
- /* 92 */ "more_keys_for_symbols_8",
- /* 93 */ "more_keys_for_symbols_9",
- /* 94 */ "more_keys_for_symbols_0",
- /* 95 */ "keylabel_for_comma",
- /* 96 */ "more_keys_for_comma",
- /* 97 */ "keylabel_for_symbols_question",
- /* 98 */ "keylabel_for_symbols_semicolon",
- /* 99 */ "keylabel_for_symbols_percent",
- /* 100 */ "more_keys_for_symbols_exclamation",
- /* 101 */ "more_keys_for_symbols_question",
- /* 102 */ "more_keys_for_symbols_semicolon",
- /* 103 */ "more_keys_for_symbols_percent",
- /* 104 */ "keylabel_for_tablet_comma",
- /* 105 */ "keyhintlabel_for_tablet_comma",
- /* 106 */ "more_keys_for_tablet_comma",
- /* 107 */ "keyhintlabel_for_period",
- /* 108 */ "more_keys_for_period",
- /* 109 */ "keylabel_for_apostrophe",
- /* 110 */ "keyhintlabel_for_apostrophe",
- /* 111 */ "more_keys_for_apostrophe",
- /* 112 */ "more_keys_for_q",
- /* 113 */ "more_keys_for_x",
- /* 114 */ "keylabel_for_q",
- /* 115 */ "keylabel_for_w",
- /* 116 */ "keylabel_for_y",
- /* 117 */ "keylabel_for_x",
- /* 118 */ "keylabel_for_spanish_row2_10",
- /* 119 */ "more_keys_for_am_pm",
- /* 120 */ "settings_as_more_key",
- /* 121 */ "shortcut_as_more_key",
- /* 122 */ "action_next_as_more_key",
- /* 123 */ "action_previous_as_more_key",
- /* 124 */ "label_to_more_symbol_key",
- /* 125 */ "label_to_more_symbol_for_tablet_key",
- /* 126 */ "label_tab_key",
- /* 127 */ "label_to_phone_numeric_key",
- /* 128 */ "label_to_phone_symbols_key",
- /* 129 */ "label_time_am",
- /* 130 */ "label_time_pm",
- /* 131 */ "keylabel_for_popular_domain",
- /* 132 */ "more_keys_for_popular_domain",
- /* 133 */ "more_keys_for_smiley",
- /* 134 */ "single_laqm_raqm",
- /* 135 */ "single_laqm_raqm_rtl",
- /* 136 */ "single_raqm_laqm",
- /* 137 */ "double_laqm_raqm",
- /* 138 */ "double_laqm_raqm_rtl",
- /* 139 */ "double_raqm_laqm",
- /* 140 */ "single_lqm_rqm",
- /* 141 */ "single_9qm_lqm",
- /* 142 */ "single_9qm_rqm",
- /* 143 */ "double_lqm_rqm",
- /* 144 */ "double_9qm_lqm",
- /* 145 */ "double_9qm_rqm",
- /* 146 */ "more_keys_for_single_quote",
- /* 147 */ "more_keys_for_double_quote",
- /* 148 */ "more_keys_for_tablet_double_quote",
- /* 149 */ "emoji_key_as_more_key",
+ /* 45 */ "keylabel_for_swiss_row1_11",
+ /* 46 */ "keylabel_for_swiss_row2_10",
+ /* 47 */ "keylabel_for_swiss_row2_11",
+ /* 48 */ "more_keys_for_swiss_row1_11",
+ /* 49 */ "more_keys_for_swiss_row2_10",
+ /* 50 */ "more_keys_for_swiss_row2_11",
+ /* 51 */ "label_to_alpha_key",
+ /* 52 */ "single_quotes",
+ /* 53 */ "double_quotes",
+ /* 54 */ "single_angle_quotes",
+ /* 55 */ "double_angle_quotes",
+ /* 56 */ "more_keys_for_currency_dollar",
+ /* 57 */ "keylabel_for_currency",
+ /* 58 */ "more_keys_for_currency",
+ /* 59 */ "more_keys_for_punctuation",
+ /* 60 */ "more_keys_for_star",
+ /* 61 */ "more_keys_for_bullet",
+ /* 62 */ "more_keys_for_plus",
+ /* 63 */ "more_keys_for_left_parenthesis",
+ /* 64 */ "more_keys_for_right_parenthesis",
+ /* 65 */ "more_keys_for_less_than",
+ /* 66 */ "more_keys_for_greater_than",
+ /* 67 */ "more_keys_for_arabic_diacritics",
+ /* 68 */ "keyhintlabel_for_arabic_diacritics",
+ /* 69 */ "keylabel_for_symbols_1",
+ /* 70 */ "keylabel_for_symbols_2",
+ /* 71 */ "keylabel_for_symbols_3",
+ /* 72 */ "keylabel_for_symbols_4",
+ /* 73 */ "keylabel_for_symbols_5",
+ /* 74 */ "keylabel_for_symbols_6",
+ /* 75 */ "keylabel_for_symbols_7",
+ /* 76 */ "keylabel_for_symbols_8",
+ /* 77 */ "keylabel_for_symbols_9",
+ /* 78 */ "keylabel_for_symbols_0",
+ /* 79 */ "label_to_symbol_key",
+ /* 80 */ "label_to_symbol_with_microphone_key",
+ /* 81 */ "additional_more_keys_for_symbols_1",
+ /* 82 */ "additional_more_keys_for_symbols_2",
+ /* 83 */ "additional_more_keys_for_symbols_3",
+ /* 84 */ "additional_more_keys_for_symbols_4",
+ /* 85 */ "additional_more_keys_for_symbols_5",
+ /* 86 */ "additional_more_keys_for_symbols_6",
+ /* 87 */ "additional_more_keys_for_symbols_7",
+ /* 88 */ "additional_more_keys_for_symbols_8",
+ /* 89 */ "additional_more_keys_for_symbols_9",
+ /* 90 */ "additional_more_keys_for_symbols_0",
+ /* 91 */ "more_keys_for_symbols_1",
+ /* 92 */ "more_keys_for_symbols_2",
+ /* 93 */ "more_keys_for_symbols_3",
+ /* 94 */ "more_keys_for_symbols_4",
+ /* 95 */ "more_keys_for_symbols_5",
+ /* 96 */ "more_keys_for_symbols_6",
+ /* 97 */ "more_keys_for_symbols_7",
+ /* 98 */ "more_keys_for_symbols_8",
+ /* 99 */ "more_keys_for_symbols_9",
+ /* 100 */ "more_keys_for_symbols_0",
+ /* 101 */ "keylabel_for_comma",
+ /* 102 */ "more_keys_for_comma",
+ /* 103 */ "keylabel_for_symbols_question",
+ /* 104 */ "keylabel_for_symbols_semicolon",
+ /* 105 */ "keylabel_for_symbols_percent",
+ /* 106 */ "more_keys_for_symbols_exclamation",
+ /* 107 */ "more_keys_for_symbols_question",
+ /* 108 */ "more_keys_for_symbols_semicolon",
+ /* 109 */ "more_keys_for_symbols_percent",
+ /* 110 */ "keylabel_for_tablet_comma",
+ /* 111 */ "keyhintlabel_for_tablet_comma",
+ /* 112 */ "more_keys_for_tablet_comma",
+ /* 113 */ "keyhintlabel_for_period",
+ /* 114 */ "more_keys_for_period",
+ /* 115 */ "keylabel_for_apostrophe",
+ /* 116 */ "keyhintlabel_for_apostrophe",
+ /* 117 */ "more_keys_for_apostrophe",
+ /* 118 */ "more_keys_for_q",
+ /* 119 */ "more_keys_for_x",
+ /* 120 */ "keylabel_for_q",
+ /* 121 */ "keylabel_for_w",
+ /* 122 */ "keylabel_for_y",
+ /* 123 */ "keylabel_for_x",
+ /* 124 */ "keylabel_for_spanish_row2_10",
+ /* 125 */ "more_keys_for_am_pm",
+ /* 126 */ "settings_as_more_key",
+ /* 127 */ "shortcut_as_more_key",
+ /* 128 */ "action_next_as_more_key",
+ /* 129 */ "action_previous_as_more_key",
+ /* 130 */ "label_to_more_symbol_key",
+ /* 131 */ "label_to_more_symbol_for_tablet_key",
+ /* 132 */ "label_tab_key",
+ /* 133 */ "label_to_phone_numeric_key",
+ /* 134 */ "label_to_phone_symbols_key",
+ /* 135 */ "label_time_am",
+ /* 136 */ "label_time_pm",
+ /* 137 */ "keylabel_for_popular_domain",
+ /* 138 */ "more_keys_for_popular_domain",
+ /* 139 */ "more_keys_for_smiley",
+ /* 140 */ "single_laqm_raqm",
+ /* 141 */ "single_laqm_raqm_rtl",
+ /* 142 */ "single_raqm_laqm",
+ /* 143 */ "double_laqm_raqm",
+ /* 144 */ "double_laqm_raqm_rtl",
+ /* 145 */ "double_raqm_laqm",
+ /* 146 */ "single_lqm_rqm",
+ /* 147 */ "single_9qm_lqm",
+ /* 148 */ "single_9qm_rqm",
+ /* 149 */ "double_lqm_rqm",
+ /* 150 */ "double_9qm_lqm",
+ /* 151 */ "double_9qm_rqm",
+ /* 152 */ "more_keys_for_single_quote",
+ /* 153 */ "more_keys_for_double_quote",
+ /* 154 */ "more_keys_for_tablet_double_quote",
+ /* 155 */ "emoji_key_as_more_key",
};
private static final String EMPTY = "";
@@ -262,145 +268,145 @@ public final class KeyboardTextsSet {
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
- EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
- /* ~44 */
+ EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
+ /* ~50 */
// Label for "switch to alphabetic" key.
- /* 45 */ "ABC",
- /* 46 */ "!text/single_lqm_rqm",
- /* 47 */ "!text/double_lqm_rqm",
- /* 48 */ "!text/single_laqm_raqm",
- /* 49 */ "!text/double_laqm_raqm",
+ /* 51 */ "ABC",
+ /* 52 */ "!text/single_lqm_rqm",
+ /* 53 */ "!text/double_lqm_rqm",
+ /* 54 */ "!text/single_laqm_raqm",
+ /* 55 */ "!text/double_laqm_raqm",
// U+00A2: "¢" CENT SIGN
// U+00A3: "£" POUND SIGN
// U+20AC: "€" EURO SIGN
// U+00A5: "¥" YEN SIGN
// U+20B1: "₱" PESO SIGN
- /* 50 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
- /* 51 */ "$",
- /* 52 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1",
- /* 53 */ "!fixedColumnOrder!4,#,!,\\,,?,-,:,',@",
+ /* 56 */ "\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
+ /* 57 */ "$",
+ /* 58 */ "$,\u00A2,\u20AC,\u00A3,\u00A5,\u20B1",
+ /* 59 */ "!fixedColumnOrder!4,#,!,\\,,?,-,:,',@",
// U+2020: "†" DAGGER
// U+2021: "‡" DOUBLE DAGGER
// U+2605: "★" BLACK STAR
- /* 54 */ "\u2020,\u2021,\u2605",
+ /* 60 */ "\u2020,\u2021,\u2605",
// U+266A: "♪" EIGHTH NOTE
// U+2665: "♥" BLACK HEART SUIT
// U+2660: "♠" BLACK SPADE SUIT
// U+2666: "♦" BLACK DIAMOND SUIT
// U+2663: "♣" BLACK CLUB SUIT
- /* 55 */ "\u266A,\u2665,\u2660,\u2666,\u2663",
+ /* 61 */ "\u266A,\u2665,\u2660,\u2666,\u2663",
// U+00B1: "±" PLUS-MINUS SIGN
- /* 56 */ "\u00B1",
+ /* 62 */ "\u00B1",
// The all letters need to be mirrored are found at
// http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
- /* 57 */ "!fixedColumnOrder!3,<,{,[",
- /* 58 */ "!fixedColumnOrder!3,>,},]",
+ /* 63 */ "!fixedColumnOrder!3,<,{,[",
+ /* 64 */ "!fixedColumnOrder!3,>,},]",
// U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
// U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
// U+2264: "≤" LESS-THAN OR EQUAL TO
// U+2265: "≥" GREATER-THAN EQUAL TO
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- /* 59 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB",
- /* 60 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB",
- /* 61 */ EMPTY,
- /* 62 */ EMPTY,
- /* 63 */ "1",
- /* 64 */ "2",
- /* 65 */ "3",
- /* 66 */ "4",
- /* 67 */ "5",
- /* 68 */ "6",
- /* 69 */ "7",
- /* 70 */ "8",
- /* 71 */ "9",
- /* 72 */ "0",
+ /* 65 */ "!fixedColumnOrder!3,\u2039,\u2264,\u00AB",
+ /* 66 */ "!fixedColumnOrder!3,\u203A,\u2265,\u00BB",
+ /* 67 */ EMPTY,
+ /* 68 */ EMPTY,
+ /* 69 */ "1",
+ /* 70 */ "2",
+ /* 71 */ "3",
+ /* 72 */ "4",
+ /* 73 */ "5",
+ /* 74 */ "6",
+ /* 75 */ "7",
+ /* 76 */ "8",
+ /* 77 */ "9",
+ /* 78 */ "0",
// Label for "switch to symbols" key.
- /* 73 */ "?123",
+ /* 79 */ "?123",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 74 */ "123",
- /* 75~ */
+ /* 80 */ "123",
+ /* 81~ */
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
- /* ~84 */
+ /* ~90 */
// U+00B9: "¹" SUPERSCRIPT ONE
// U+00BD: "½" VULGAR FRACTION ONE HALF
// U+2153: "⅓" VULGAR FRACTION ONE THIRD
// U+00BC: "¼" VULGAR FRACTION ONE QUARTER
// U+215B: "⅛" VULGAR FRACTION ONE EIGHTH
- /* 85 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B",
+ /* 91 */ "\u00B9,\u00BD,\u2153,\u00BC,\u215B",
// U+00B2: "²" SUPERSCRIPT TWO
// U+2154: "⅔" VULGAR FRACTION TWO THIRDS
- /* 86 */ "\u00B2,\u2154",
+ /* 92 */ "\u00B2,\u2154",
// U+00B3: "³" SUPERSCRIPT THREE
// U+00BE: "¾" VULGAR FRACTION THREE QUARTERS
// U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS
- /* 87 */ "\u00B3,\u00BE,\u215C",
+ /* 93 */ "\u00B3,\u00BE,\u215C",
// U+2074: "⁴" SUPERSCRIPT FOUR
- /* 88 */ "\u2074",
+ /* 94 */ "\u2074",
// U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS
- /* 89 */ "\u215D",
- /* 90 */ EMPTY,
+ /* 95 */ "\u215D",
+ /* 96 */ EMPTY,
// U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS
- /* 91 */ "\u215E",
- /* 92 */ EMPTY,
- /* 93 */ EMPTY,
+ /* 97 */ "\u215E",
+ /* 98 */ EMPTY,
+ /* 99 */ EMPTY,
// U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N
// U+2205: "∅" EMPTY SET
- /* 94 */ "\u207F,\u2205",
- /* 95 */ ",",
- /* 96 */ EMPTY,
- /* 97 */ "?",
- /* 98 */ ";",
- /* 99 */ "%",
+ /* 100 */ "\u207F,\u2205",
+ /* 101 */ ",",
+ /* 102 */ EMPTY,
+ /* 103 */ "?",
+ /* 104 */ ";",
+ /* 105 */ "%",
// U+00A1: "¡" INVERTED EXCLAMATION MARK
- /* 100 */ "\u00A1",
+ /* 106 */ "\u00A1",
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 101 */ "\u00BF",
- /* 102 */ EMPTY,
+ /* 107 */ "\u00BF",
+ /* 108 */ EMPTY,
// U+2030: "‰" PER MILLE SIGN
- /* 103 */ "\u2030",
- /* 104 */ ",",
- /* 105~ */
+ /* 109 */ "\u2030",
+ /* 110 */ ",",
+ /* 111~ */
EMPTY, EMPTY, EMPTY,
- /* ~107 */
+ /* ~113 */
// U+2026: "…" HORIZONTAL ELLIPSIS
- /* 108 */ "\u2026",
- /* 109 */ "\'",
- /* 110 */ "\"",
- /* 111 */ "\"",
- /* 112 */ EMPTY,
- /* 113 */ EMPTY,
- /* 114 */ "q",
- /* 115 */ "w",
- /* 116 */ "y",
- /* 117 */ "x",
+ /* 114 */ "\u2026",
+ /* 115 */ "\'",
+ /* 116 */ "\"",
+ /* 117 */ "\"",
/* 118 */ EMPTY,
- /* 119 */ "!fixedColumnOrder!2,!hasLabels!,!text/label_time_am,!text/label_time_pm",
- /* 120 */ "!icon/settings_key|!code/key_settings",
- /* 121 */ "!icon/shortcut_key|!code/key_shortcut",
- /* 122 */ "!hasLabels!,!text/label_next_key|!code/key_action_next",
- /* 123 */ "!hasLabels!,!text/label_previous_key|!code/key_action_previous",
+ /* 119 */ EMPTY,
+ /* 120 */ "q",
+ /* 121 */ "w",
+ /* 122 */ "y",
+ /* 123 */ "x",
+ /* 124 */ EMPTY,
+ /* 125 */ "!fixedColumnOrder!2,!hasLabels!,!text/label_time_am,!text/label_time_pm",
+ /* 126 */ "!icon/settings_key|!code/key_settings",
+ /* 127 */ "!icon/shortcut_key|!code/key_shortcut",
+ /* 128 */ "!hasLabels!,!text/label_next_key|!code/key_action_next",
+ /* 129 */ "!hasLabels!,!text/label_previous_key|!code/key_action_previous",
// Label for "switch to more symbol" modifier key. Must be short to fit on key!
- /* 124 */ "= \\ <",
+ /* 130 */ "= \\ <",
// Label for "switch to more symbol" modifier key on tablets. Must be short to fit on key!
- /* 125 */ "~ [ <",
+ /* 131 */ "~ [ <",
// Label for "Tab" key. Must be short to fit on key!
- /* 126 */ "Tab",
+ /* 132 */ "Tab",
// Label for "switch to phone numeric" key. Must be short to fit on key!
- /* 127 */ "123",
+ /* 133 */ "123",
// Label for "switch to phone symbols" key. Must be short to fit on key!
// U+FF0A: "*" FULLWIDTH ASTERISK
// U+FF03: "#" FULLWIDTH NUMBER SIGN
- /* 128 */ "\uFF0A\uFF03",
+ /* 134 */ "\uFF0A\uFF03",
// Key label for "ante meridiem"
- /* 129 */ "AM",
+ /* 135 */ "AM",
// Key label for "post meridiem"
- /* 130 */ "PM",
- /* 131 */ ".com",
+ /* 136 */ "PM",
+ /* 137 */ ".com",
// popular web domains for the locale - most popular, displayed on the keyboard
- /* 132 */ "!hasLabels!,.net,.org,.gov,.edu",
- /* 133 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ",
+ /* 138 */ "!hasLabels!,.net,.org,.gov,.edu",
+ /* 139 */ "!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ ",
// U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
// U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
@@ -422,25 +428,25 @@ public final class KeyboardTextsSet {
// The following each quotation mark pair consist of
// <opening quotation mark>, <closing quotation mark>
// and is named after (single|double)_<opening quotation mark>_<closing quotation mark>.
- /* 134 */ "\u2039,\u203A",
- /* 135 */ "\u2039|\u203A,\u203A|\u2039",
- /* 136 */ "\u203A,\u2039",
- /* 137 */ "\u00AB,\u00BB",
- /* 138 */ "\u00AB|\u00BB,\u00BB|\u00AB",
- /* 139 */ "\u00BB,\u00AB",
+ /* 140 */ "\u2039,\u203A",
+ /* 141 */ "\u2039|\u203A,\u203A|\u2039",
+ /* 142 */ "\u203A,\u2039",
+ /* 143 */ "\u00AB,\u00BB",
+ /* 144 */ "\u00AB|\u00BB,\u00BB|\u00AB",
+ /* 145 */ "\u00BB,\u00AB",
// The following each quotation mark triplet consists of
// <another quotation mark>, <opening quotation mark>, <closing quotation mark>
// and is named after (single|double)_<opening quotation mark>_<closing quotation mark>.
- /* 140 */ "\u201A,\u2018,\u2019",
- /* 141 */ "\u2019,\u201A,\u2018",
- /* 142 */ "\u2018,\u201A,\u2019",
- /* 143 */ "\u201E,\u201C,\u201D",
- /* 144 */ "\u201D,\u201E,\u201C",
- /* 145 */ "\u201C,\u201E,\u201D",
- /* 146 */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes",
- /* 147 */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes",
- /* 148 */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes",
- /* 149 */ "!icon/emoji_key|!code/key_emoji",
+ /* 146 */ "\u201A,\u2018,\u2019",
+ /* 147 */ "\u2019,\u201A,\u2018",
+ /* 148 */ "\u2018,\u201A,\u2019",
+ /* 149 */ "\u201E,\u201C,\u201D",
+ /* 150 */ "\u201D,\u201E,\u201C",
+ /* 151 */ "\u201C,\u201E,\u201D",
+ /* 152 */ "!fixedColumnOrder!5,!text/single_quotes,!text/single_angle_quotes",
+ /* 153 */ "!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes",
+ /* 154 */ "!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes",
+ /* 155 */ "!icon/emoji_key|!code/key_emoji",
};
/* Language af: Afrikaans */
@@ -502,44 +508,45 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0623: "ا" ARABIC LETTER ALEF
// U+200C: ZERO WIDTH NON-JOINER
// U+0628: "ب" ARABIC LETTER BEH
// U+062C: "پ" ARABIC LETTER PEH
- /* 45 */ "\u0623\u200C\u0628\u200C\u062C",
- /* 46 */ null,
- /* 47 */ null,
- /* 48 */ "!text/single_laqm_raqm_rtl",
- /* 49 */ "!text/double_laqm_raqm_rtl",
- /* 50~ */
+ /* 51 */ "\u0623\u200C\u0628\u200C\u062C",
+ /* 52 */ null,
+ /* 53 */ null,
+ /* 54 */ "!text/single_laqm_raqm_rtl",
+ /* 55 */ "!text/double_laqm_raqm_rtl",
+ /* 56~ */
null, null, null,
- /* ~52 */
+ /* ~58 */
// U+061F: "؟" ARABIC QUESTION MARK
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
- /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(",
+ /* 59 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(",
// U+2605: "★" BLACK STAR
// U+066D: "٭" ARABIC FIVE POINTED STAR
- /* 54 */ "\u2605,\u066D",
+ /* 60 */ "\u2605,\u066D",
// U+266A: "♪" EIGHTH NOTE
- /* 55 */ "\u266A",
- /* 56 */ null,
+ /* 61 */ "\u266A",
+ /* 62 */ null,
// The all letters need to be mirrored are found at
// http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
// U+FD3E: "﴾" ORNATE LEFT PARENTHESIS
// U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS
- /* 57 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
- /* 58 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
+ /* 63 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 64 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
// U+2264: "≤" LESS-THAN OR EQUAL TO
// U+2265: "≥" GREATER-THAN EQUAL TO
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
// U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
- /* 59 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
- /* 60 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 65 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 66 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
// U+0655: "ٕ" ARABIC HAMZA BELOW
// U+0654: "ٔ" ARABIC HAMZA ABOVE
// U+0652: "ْ" ARABIC SUKUN
@@ -556,70 +563,70 @@ public final class KeyboardTextsSet {
// U+0640: "ـ" ARABIC TATWEEL
// In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
// Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
- /* 61 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
- /* 62 */ "\u0651",
+ /* 67 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
+ /* 68 */ "\u0651",
// U+0661: "١" ARABIC-INDIC DIGIT ONE
- /* 63 */ "\u0661",
+ /* 69 */ "\u0661",
// U+0662: "٢" ARABIC-INDIC DIGIT TWO
- /* 64 */ "\u0662",
+ /* 70 */ "\u0662",
// U+0663: "٣" ARABIC-INDIC DIGIT THREE
- /* 65 */ "\u0663",
+ /* 71 */ "\u0663",
// U+0664: "٤" ARABIC-INDIC DIGIT FOUR
- /* 66 */ "\u0664",
+ /* 72 */ "\u0664",
// U+0665: "٥" ARABIC-INDIC DIGIT FIVE
- /* 67 */ "\u0665",
+ /* 73 */ "\u0665",
// U+0666: "٦" ARABIC-INDIC DIGIT SIX
- /* 68 */ "\u0666",
+ /* 74 */ "\u0666",
// U+0667: "٧" ARABIC-INDIC DIGIT SEVEN
- /* 69 */ "\u0667",
+ /* 75 */ "\u0667",
// U+0668: "٨" ARABIC-INDIC DIGIT EIGHT
- /* 70 */ "\u0668",
+ /* 76 */ "\u0668",
// U+0669: "٩" ARABIC-INDIC DIGIT NINE
- /* 71 */ "\u0669",
+ /* 77 */ "\u0669",
// U+0660: "٠" ARABIC-INDIC DIGIT ZERO
- /* 72 */ "\u0660",
+ /* 78 */ "\u0660",
// Label for "switch to symbols" key.
// U+061F: "؟" ARABIC QUESTION MARK
- /* 73 */ "\u0663\u0662\u0661\u061F",
+ /* 79 */ "\u0663\u0662\u0661\u061F",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 74 */ "\u0663\u0662\u0661",
- /* 75 */ "1",
- /* 76 */ "2",
- /* 77 */ "3",
- /* 78 */ "4",
- /* 79 */ "5",
- /* 80 */ "6",
- /* 81 */ "7",
- /* 82 */ "8",
- /* 83 */ "9",
+ /* 80 */ "\u0663\u0662\u0661",
+ /* 81 */ "1",
+ /* 82 */ "2",
+ /* 83 */ "3",
+ /* 84 */ "4",
+ /* 85 */ "5",
+ /* 86 */ "6",
+ /* 87 */ "7",
+ /* 88 */ "8",
+ /* 89 */ "9",
// U+066B: "٫" ARABIC DECIMAL SEPARATOR
// U+066C: "٬" ARABIC THOUSANDS SEPARATOR
- /* 84 */ "0,\u066B,\u066C",
- /* 85~ */
+ /* 90 */ "0,\u066B,\u066C",
+ /* 91~ */
null, null, null, null, null, null, null, null, null, null,
- /* ~94 */
+ /* ~100 */
// U+060C: "،" ARABIC COMMA
- /* 95 */ "\u060C",
- /* 96 */ "\\,",
- /* 97 */ "\u061F",
- /* 98 */ "\u061B",
+ /* 101 */ "\u060C",
+ /* 102 */ "\\,",
+ /* 103 */ "\u061F",
+ /* 104 */ "\u061B",
// U+066A: "٪" ARABIC PERCENT SIGN
- /* 99 */ "\u066A",
- /* 100 */ null,
- /* 101 */ "?",
- /* 102 */ ";",
+ /* 105 */ "\u066A",
+ /* 106 */ null,
+ /* 107 */ "?",
+ /* 108 */ ";",
// U+2030: "‰" PER MILLE SIGN
- /* 103 */ "\\%,\u2030",
- /* 104~ */
+ /* 109 */ "\\%,\u2030",
+ /* 110~ */
null, null, null, null, null,
- /* ~108 */
+ /* ~114 */
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
// U+061F: "؟" ARABIC QUESTION MARK
- /* 109 */ "\u060C",
- /* 110 */ "\u061F",
- /* 111 */ "\u061F,\u061B,!,:,-,/,\',\"",
+ /* 115 */ "\u060C",
+ /* 116 */ "\u061F",
+ /* 117 */ "\u061F,\u061B,!,:,-,/,\',\"",
};
/* Language az: Azerbaijani */
@@ -694,14 +701,16 @@ public final class KeyboardTextsSet {
/* ~42 */
// U+0451: "ё" CYRILLIC SMALL LETTER IO
/* 43 */ "\u0451",
- /* 44 */ null,
+ /* 44~ */
+ null, null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ /* 51 */ "\u0410\u0411\u0412",
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language bg: Bulgarian */
@@ -710,15 +719,16 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
- /* 46 */ null,
+ /* 51 */ "\u0410\u0411\u0412",
+ /* 52 */ null,
// single_quotes of Bulgarian is default single_quotes_right_left.
- /* 47 */ "!text/double_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language ca: Catalan */
@@ -782,22 +792,22 @@ public final class KeyboardTextsSet {
/* 15~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null,
- /* ~52 */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~58 */
// U+00B7: "·" MIDDLE DOT
- /* 53 */ "!fixedColumnOrder!4,\u00B7,!,\\,,?,:,;,@",
- /* 54~ */
+ /* 59 */ "!fixedColumnOrder!4,\u00B7,!,\\,,?,:,;,@",
+ /* 60~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null,
- /* ~107 */
- /* 108 */ "?,\u00B7",
- /* 109~ */
+ /* ~113 */
+ /* 114 */ "?,\u00B7",
+ /* 115~ */
null, null, null, null, null, null, null, null, null,
- /* ~117 */
+ /* ~123 */
// U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
- /* 118 */ "\u00E7",
+ /* 124 */ "\u00E7",
};
/* Language cs: Czech */
@@ -871,12 +881,12 @@ public final class KeyboardTextsSet {
/* 13~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language da: Danish */
@@ -940,12 +950,12 @@ public final class KeyboardTextsSet {
/* 24 */ "\u00F6",
/* 25~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language de: German */
@@ -991,12 +1001,25 @@ public final class KeyboardTextsSet {
/* 7~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null, null, null,
+ /* ~44 */
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ /* 45 */ "\u00FC",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ /* 46 */ "\u00F6",
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ /* 47 */ "\u00E4",
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ /* 48 */ "\u00E8",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ /* 49 */ "\u00E9",
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ /* 50 */ "\u00E0",
+ /* 51 */ null,
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language el: Greek */
@@ -1005,12 +1028,13 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0391: "Α" GREEK CAPITAL LETTER ALPHA
// U+0392: "Β" GREEK CAPITAL LETTER BETA
// U+0393: "Γ" GREEK CAPITAL LETTER GAMMA
- /* 45 */ "\u0391\u0392\u0393",
+ /* 51 */ "\u0391\u0392\u0393",
};
/* Language en: English */
@@ -1182,20 +1206,20 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null,
- /* ~111 */
- /* 112 */ "q",
- /* 113 */ "x",
+ null, null, null, null, null, null, null, null,
+ /* ~117 */
+ /* 118 */ "q",
+ /* 119 */ "x",
// U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX
- /* 114 */ "\u015D",
+ /* 120 */ "\u015D",
// U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX
- /* 115 */ "\u011D",
+ /* 121 */ "\u011D",
// U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE
- /* 116 */ "\u016D",
+ /* 122 */ "\u016D",
// U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX
- /* 117 */ "\u0109",
+ /* 123 */ "\u0109",
// U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
- /* 118 */ "\u0135",
+ /* 124 */ "\u0135",
};
/* Language es: Spanish */
@@ -1254,29 +1278,30 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~52 */
+ null, null, null, null, null, null,
+ /* ~58 */
// U+00A1: "¡" INVERTED EXCLAMATION MARK
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 53 */ "!fixedColumnOrder!4,;,!,\\,,?,:,\u00A1,@,\u00BF",
- /* 54~ */
+ /* 59 */ "!fixedColumnOrder!4,;,!,\\,,?,:,\u00A1,@,\u00BF",
+ /* 60~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null,
- /* ~105 */
+ /* ~111 */
// U+00A1: "¡" INVERTED EXCLAMATION MARK
- /* 106 */ "!,\u00A1",
- /* 107 */ null,
+ /* 112 */ "!,\u00A1",
+ /* 113 */ null,
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 108 */ "?,\u00BF",
- /* 109 */ "\"",
- /* 110 */ "\'",
- /* 111 */ "\'",
- /* 112~ */
+ /* 114 */ "?,\u00BF",
+ /* 115 */ "\"",
+ /* 116 */ "\'",
+ /* 117 */ "\'",
+ /* 118~ */
null, null, null, null, null, null,
- /* ~117 */
+ /* ~123 */
// U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
- /* 118 */ "\u00F1",
+ /* 124 */ "\u00F1",
};
/* Language et: Estonian */
@@ -1379,10 +1404,10 @@ public final class KeyboardTextsSet {
/* 23 */ "\u00F5",
/* 24~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language fa: Persian */
@@ -1391,45 +1416,46 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0627: "ا" ARABIC LETTER ALEF
// U+200C: ZERO WIDTH NON-JOINER
// U+0628: "ب" ARABIC LETTER BEH
// U+067E: "پ" ARABIC LETTER PEH
- /* 45 */ "\u0627\u200C\u0628\u200C\u067E",
- /* 46 */ null,
- /* 47 */ null,
- /* 48 */ "!text/single_laqm_raqm_rtl",
- /* 49 */ "!text/double_laqm_raqm_rtl",
- /* 50 */ null,
- // U+FDFC: "﷼" RIAL SIGN
- /* 51 */ "\uFDFC",
+ /* 51 */ "\u0627\u200C\u0628\u200C\u067E",
/* 52 */ null,
+ /* 53 */ null,
+ /* 54 */ "!text/single_laqm_raqm_rtl",
+ /* 55 */ "!text/double_laqm_raqm_rtl",
+ /* 56 */ null,
+ // U+FDFC: "﷼" RIAL SIGN
+ /* 57 */ "\uFDFC",
+ /* 58 */ null,
// U+061F: "؟" ARABIC QUESTION MARK
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
- /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(",
+ /* 59 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(",
// U+2605: "★" BLACK STAR
// U+066D: "٭" ARABIC FIVE POINTED STAR
- /* 54 */ "\u2605,\u066D",
+ /* 60 */ "\u2605,\u066D",
// U+266A: "♪" EIGHTH NOTE
- /* 55 */ "\u266A",
- /* 56 */ null,
+ /* 61 */ "\u266A",
+ /* 62 */ null,
// The all letters need to be mirrored are found at
// http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
// U+FD3E: "﴾" ORNATE LEFT PARENTHESIS
// U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS
- /* 57 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
- /* 58 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
+ /* 63 */ "!fixedColumnOrder!4,\uFD3E|\uFD3F,<|>,{|},[|]",
+ /* 64 */ "!fixedColumnOrder!4,\uFD3F|\uFD3E,>|<,}|{,]|[",
// U+2264: "≤" LESS-THAN OR EQUAL TO
// U+2265: "≥" GREATER-THAN EQUAL TO
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
// U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
- /* 59 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,<|>",
- /* 60 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,>|<",
+ /* 65 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,<|>",
+ /* 66 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,>|<",
// U+0655: "ٕ" ARABIC HAMZA BELOW
// U+0652: "ْ" ARABIC SUKUN
// U+0651: "ّ" ARABIC SHADDA
@@ -1446,74 +1472,74 @@ public final class KeyboardTextsSet {
// U+0640: "ـ" ARABIC TATWEEL
// In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label.
// Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
- /* 61 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
- /* 62 */ "\u064B",
+ /* 67 */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
+ /* 68 */ "\u064B",
// U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE
- /* 63 */ "\u06F1",
+ /* 69 */ "\u06F1",
// U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO
- /* 64 */ "\u06F2",
+ /* 70 */ "\u06F2",
// U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE
- /* 65 */ "\u06F3",
+ /* 71 */ "\u06F3",
// U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR
- /* 66 */ "\u06F4",
+ /* 72 */ "\u06F4",
// U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE
- /* 67 */ "\u06F5",
+ /* 73 */ "\u06F5",
// U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX
- /* 68 */ "\u06F6",
+ /* 74 */ "\u06F6",
// U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN
- /* 69 */ "\u06F7",
+ /* 75 */ "\u06F7",
// U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT
- /* 70 */ "\u06F8",
+ /* 76 */ "\u06F8",
// U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE
- /* 71 */ "\u06F9",
+ /* 77 */ "\u06F9",
// U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO
- /* 72 */ "\u06F0",
+ /* 78 */ "\u06F0",
// Label for "switch to symbols" key.
// U+061F: "؟" ARABIC QUESTION MARK
- /* 73 */ "\u06F3\u06F2\u06F1\u061F",
+ /* 79 */ "\u06F3\u06F2\u06F1\u061F",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 74 */ "\u06F3\u06F2\u06F1",
- /* 75 */ "1",
- /* 76 */ "2",
- /* 77 */ "3",
- /* 78 */ "4",
- /* 79 */ "5",
- /* 80 */ "6",
- /* 81 */ "7",
- /* 82 */ "8",
- /* 83 */ "9",
+ /* 80 */ "\u06F3\u06F2\u06F1",
+ /* 81 */ "1",
+ /* 82 */ "2",
+ /* 83 */ "3",
+ /* 84 */ "4",
+ /* 85 */ "5",
+ /* 86 */ "6",
+ /* 87 */ "7",
+ /* 88 */ "8",
+ /* 89 */ "9",
// U+066B: "٫" ARABIC DECIMAL SEPARATOR
// U+066C: "٬" ARABIC THOUSANDS SEPARATOR
- /* 84 */ "0,\u066B,\u066C",
- /* 85~ */
+ /* 90 */ "0,\u066B,\u066C",
+ /* 91~ */
null, null, null, null, null, null, null, null, null, null,
- /* ~94 */
+ /* ~100 */
// U+060C: "،" ARABIC COMMA
- /* 95 */ "\u060C",
- /* 96 */ "\\,",
- /* 97 */ "\u061F",
- /* 98 */ "\u061B",
+ /* 101 */ "\u060C",
+ /* 102 */ "\\,",
+ /* 103 */ "\u061F",
+ /* 104 */ "\u061B",
// U+066A: "٪" ARABIC PERCENT SIGN
- /* 99 */ "\u066A",
- /* 100 */ null,
- /* 101 */ "?",
- /* 102 */ ";",
+ /* 105 */ "\u066A",
+ /* 106 */ null,
+ /* 107 */ "?",
+ /* 108 */ ";",
// U+2030: "‰" PER MILLE SIGN
- /* 103 */ "\\%,\u2030",
+ /* 109 */ "\\%,\u2030",
// U+060C: "،" ARABIC COMMA
// U+061B: "؛" ARABIC SEMICOLON
// U+061F: "؟" ARABIC QUESTION MARK
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- /* 104 */ "\u060C",
- /* 105 */ "!",
- /* 106 */ "!,\\,",
- /* 107 */ "\u061F",
- /* 108 */ "\u061F,?",
- /* 109 */ "\u060C",
- /* 110 */ "\u061F",
- /* 111 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\u00AB|\u00BB,\u00BB|\u00AB",
+ /* 110 */ "\u060C",
+ /* 111 */ "!",
+ /* 112 */ "!,\\,",
+ /* 113 */ "\u061F",
+ /* 114 */ "\u061F,?",
+ /* 115 */ "\u060C",
+ /* 116 */ "\u061F",
+ /* 117 */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,/,\u00AB|\u00BB,\u00BB|\u00AB",
};
/* Language fi: Finnish */
@@ -1614,6 +1640,23 @@ public final class KeyboardTextsSet {
/* 7 */ "\u00E7,\u0107,\u010D",
// U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
/* 8 */ "%,\u00FF",
+ /* 9~ */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null, null, null, null, null,
+ /* ~44 */
+ // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+ /* 45 */ "\u00E8",
+ // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+ /* 46 */ "\u00E9",
+ // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+ /* 47 */ "\u00E0",
+ // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+ /* 48 */ "\u00FC",
+ // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+ /* 49 */ "\u00F6",
+ // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+ /* 50 */ "\u00E4",
};
/* Language hi: Hindi */
@@ -1622,55 +1665,56 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0915: "क" DEVANAGARI LETTER KA
// U+0916: "ख" DEVANAGARI LETTER KHA
// U+0917: "ग" DEVANAGARI LETTER GA
- /* 45 */ "\u0915\u0916\u0917",
- /* 46~ */
+ /* 51 */ "\u0915\u0916\u0917",
+ /* 52~ */
null, null, null, null, null,
- /* ~50 */
+ /* ~56 */
// U+20B9: "₹" INDIAN RUPEE SIGN
- /* 51 */ "\u20B9",
- /* 52~ */
+ /* 57 */ "\u20B9",
+ /* 58~ */
null, null, null, null, null, null, null, null, null, null, null,
- /* ~62 */
+ /* ~68 */
// U+0967: "१" DEVANAGARI DIGIT ONE
- /* 63 */ "\u0967",
+ /* 69 */ "\u0967",
// U+0968: "२" DEVANAGARI DIGIT TWO
- /* 64 */ "\u0968",
+ /* 70 */ "\u0968",
// U+0969: "३" DEVANAGARI DIGIT THREE
- /* 65 */ "\u0969",
+ /* 71 */ "\u0969",
// U+096A: "४" DEVANAGARI DIGIT FOUR
- /* 66 */ "\u096A",
+ /* 72 */ "\u096A",
// U+096B: "५" DEVANAGARI DIGIT FIVE
- /* 67 */ "\u096B",
+ /* 73 */ "\u096B",
// U+096C: "६" DEVANAGARI DIGIT SIX
- /* 68 */ "\u096C",
+ /* 74 */ "\u096C",
// U+096D: "७" DEVANAGARI DIGIT SEVEN
- /* 69 */ "\u096D",
+ /* 75 */ "\u096D",
// U+096E: "८" DEVANAGARI DIGIT EIGHT
- /* 70 */ "\u096E",
+ /* 76 */ "\u096E",
// U+096F: "९" DEVANAGARI DIGIT NINE
- /* 71 */ "\u096F",
+ /* 77 */ "\u096F",
// U+0966: "०" DEVANAGARI DIGIT ZERO
- /* 72 */ "\u0966",
+ /* 78 */ "\u0966",
// Label for "switch to symbols" key.
- /* 73 */ "?\u0967\u0968\u0969",
+ /* 79 */ "?\u0967\u0968\u0969",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 74 */ "\u0967\u0968\u0969",
- /* 75 */ "1",
- /* 76 */ "2",
- /* 77 */ "3",
- /* 78 */ "4",
- /* 79 */ "5",
- /* 80 */ "6",
- /* 81 */ "7",
- /* 82 */ "8",
- /* 83 */ "9",
- /* 84 */ "0",
+ /* 80 */ "\u0967\u0968\u0969",
+ /* 81 */ "1",
+ /* 82 */ "2",
+ /* 83 */ "3",
+ /* 84 */ "4",
+ /* 85 */ "5",
+ /* 86 */ "6",
+ /* 87 */ "7",
+ /* 88 */ "8",
+ /* 89 */ "9",
+ /* 90 */ "0",
};
/* Language hr: Croatian */
@@ -1701,12 +1745,12 @@ public final class KeyboardTextsSet {
/* 13~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_rqm",
- /* 47 */ "!text/double_9qm_rqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_rqm",
+ /* 53 */ "!text/double_9qm_rqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language hu: Hungarian */
@@ -1755,12 +1799,13 @@ public final class KeyboardTextsSet {
/* 5~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_rqm",
- /* 47 */ "!text/double_9qm_rqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_rqm",
+ /* 53 */ "!text/double_9qm_rqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language hy: Armenian */
@@ -1769,8 +1814,8 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null,
- /* ~52 */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~58 */
// U+058A: "֊" ARMENIAN HYPHEN
// U+055C: "՜" ARMENIAN EXCLAMATION MARK
// U+055D: "՝" ARMENIAN COMMA
@@ -1779,19 +1824,19 @@ public final class KeyboardTextsSet {
// U+055A: "՚" ARMENIAN APOSTROPHE
// U+055B: "՛" ARMENIAN EMPHASIS MARK
// U+055F: "՟" ARMENIAN ABBREVIATION MARK
- /* 53 */ "!fixedColumnOrder!8,!,?,\\,,.,\u058A,\u055C,\u055D,\u055E,:,;,@,\u0559,\u055A,\u055B,\u055F",
- /* 54~ */
+ /* 59 */ "!fixedColumnOrder!8,!,?,\\,,.,\u058A,\u055C,\u055D,\u055E,:,;,@,\u0559,\u055A,\u055B,\u055F",
+ /* 60~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null,
- /* ~99 */
+ /* ~105 */
// U+055C: "՜" ARMENIAN EXCLAMATION MARK
// U+00A1: "¡" INVERTED EXCLAMATION MARK
- /* 100 */ "\u055C,\u00A1",
+ /* 106 */ "\u055C,\u00A1",
// U+055E: "՞" ARMENIAN QUESTION MARK
// U+00BF: "¿" INVERTED QUESTION MARK
- /* 101 */ "\u055E,\u00BF",
+ /* 107 */ "\u055E,\u00BF",
};
/* Language is: Icelandic */
@@ -1857,10 +1902,10 @@ public final class KeyboardTextsSet {
/* 22 */ "\u00FE",
/* 23~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language it: Italian */
@@ -1914,12 +1959,13 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+05D0: "א" HEBREW LETTER ALEF
// U+05D1: "ב" HEBREW LETTER BET
// U+05D2: "ג" HEBREW LETTER GIMEL
- /* 45 */ "\u05D0\u05D1\u05D2",
+ /* 51 */ "\u05D0\u05D1\u05D2",
// The following characters don't need BIDI mirroring.
// U+2018: "‘" LEFT SINGLE QUOTATION MARK
// U+2019: "’" RIGHT SINGLE QUOTATION MARK
@@ -1927,42 +1973,42 @@ public final class KeyboardTextsSet {
// U+201C: "“" LEFT DOUBLE QUOTATION MARK
// U+201D: "”" RIGHT DOUBLE QUOTATION MARK
// U+201E: "„" DOUBLE LOW-9 QUOTATION MARK
- /* 46 */ "\u2018,\u2019,\u201A",
- /* 47 */ "\u201C,\u201D,\u201E",
- /* 48 */ "!text/single_laqm_raqm_rtl",
- /* 49 */ "!text/double_laqm_raqm_rtl",
- /* 50 */ null,
+ /* 52 */ "\u2018,\u2019,\u201A",
+ /* 53 */ "\u201C,\u201D,\u201E",
+ /* 54 */ "!text/single_laqm_raqm_rtl",
+ /* 55 */ "!text/double_laqm_raqm_rtl",
+ /* 56 */ null,
// U+20AA: "₪" NEW SHEQEL SIGN
- /* 51 */ "\u20AA",
- /* 52 */ null,
- /* 53 */ null,
+ /* 57 */ "\u20AA",
+ /* 58 */ null,
+ /* 59 */ null,
// U+2605: "★" BLACK STAR
- /* 54 */ "\u2605",
- /* 55 */ null,
+ /* 60 */ "\u2605",
+ /* 61 */ null,
// U+00B1: "±" PLUS-MINUS SIGN
// U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
- /* 56 */ "\u00B1,\uFB29",
+ /* 62 */ "\u00B1,\uFB29",
// The all letters need to be mirrored are found at
// http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt
- /* 57 */ "!fixedColumnOrder!3,<|>,{|},[|]",
- /* 58 */ "!fixedColumnOrder!3,>|<,}|{,]|[",
+ /* 63 */ "!fixedColumnOrder!3,<|>,{|},[|]",
+ /* 64 */ "!fixedColumnOrder!3,>|<,}|{,]|[",
// U+2264: "≤" LESS-THAN OR EQUAL TO
// U+2265: "≥" GREATER-THAN EQUAL TO
// U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
// U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
// U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
- /* 59 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
- /* 60 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
- /* 61~ */
+ /* 65 */ "!fixedColumnOrder!3,\u2039|\u203A,\u2264|\u2265,\u00AB|\u00BB",
+ /* 66 */ "!fixedColumnOrder!3,\u203A|\u2039,\u2265|\u2264,\u00BB|\u00AB",
+ /* 67~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~104 */
- /* 105 */ "!",
- /* 106 */ "!",
- /* 107 */ "?",
- /* 108 */ "?",
+ /* ~110 */
+ /* 111 */ "!",
+ /* 112 */ "!",
+ /* 113 */ "?",
+ /* 114 */ "?",
};
/* Language ka: Georgian */
@@ -1971,14 +2017,15 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+10D0: "ა" GEORGIAN LETTER AN
// U+10D1: "ბ" GEORGIAN LETTER BAN
// U+10D2: "გ" GEORGIAN LETTER GAN
- /* 45 */ "\u10D0\u10D1\u10D2",
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ /* 51 */ "\u10D0\u10D1\u10D2",
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language kk: Kazakh */
@@ -2021,12 +2068,14 @@ public final class KeyboardTextsSet {
/* ~42 */
// U+0451: "ё" CYRILLIC SMALL LETTER IO
/* 43 */ "\u0451",
- /* 44 */ null,
+ /* 44~ */
+ null, null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
+ /* 51 */ "\u0410\u0411\u0412",
};
/* Language km: Khmer */
@@ -2035,17 +2084,18 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+1780: "ក" KHMER LETTER KA
// U+1781: "ខ" KHMER LETTER KHA
// U+1782: "គ" KHMER LETTER KO
- /* 45 */ "\u1780\u1781\u1782",
- /* 46~ */
+ /* 51 */ "\u1780\u1781\u1782",
+ /* 52~ */
null, null, null, null,
- /* ~49 */
+ /* ~55 */
// U+17DB: "៛" KHMER CURRENCY SYMBOL RIEL
- /* 50 */ "\u17DB,\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
+ /* 56 */ "\u17DB,\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
};
/* Language ky: Kirghiz */
@@ -2081,12 +2131,14 @@ public final class KeyboardTextsSet {
/* ~42 */
// U+0451: "ё" CYRILLIC SMALL LETTER IO
/* 43 */ "\u0451",
- /* 44 */ null,
+ /* 44~ */
+ null, null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
+ /* 51 */ "\u0410\u0411\u0412",
};
/* Language lo: Lao */
@@ -2095,17 +2147,18 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0E81: "ກ" LAO LETTER KO
// U+0E82: "ຂ" LAO LETTER KHO SUNG
// U+0E84: "ຄ" LAO LETTER KHO TAM
- /* 45 */ "\u0E81\u0E82\u0E84",
- /* 46~ */
+ /* 51 */ "\u0E81\u0E82\u0E84",
+ /* 52~ */
null, null, null, null, null,
- /* ~50 */
+ /* ~56 */
// U+20AD: "₭" KIP SIGN
- /* 51 */ "\u20AD",
+ /* 57 */ "\u20AD",
};
/* Language lt: Lithuanian */
@@ -2199,9 +2252,10 @@ public final class KeyboardTextsSet {
/* 16~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language lv: Latvian */
@@ -2294,9 +2348,10 @@ public final class KeyboardTextsSet {
/* 16~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language mk: Macedonian */
@@ -2318,13 +2373,16 @@ public final class KeyboardTextsSet {
/* 43 */ "\u0450",
// U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
/* 44 */ "\u045D",
+ /* 45~ */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ /* 51 */ "\u0410\u0411\u0412",
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language mn: Mongolian */
@@ -2333,17 +2391,18 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
- /* 46~ */
+ /* 51 */ "\u0410\u0411\u0412",
+ /* 52~ */
null, null, null, null, null,
- /* ~50 */
+ /* ~56 */
// U+20AE: "₮" TUGRIK SIGN
- /* 51 */ "\u20AE",
+ /* 57 */ "\u20AE",
};
/* Language nb: Norwegian Bokmål */
@@ -2393,10 +2452,10 @@ public final class KeyboardTextsSet {
/* 24 */ "\u00E4",
/* 25~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_rqm",
- /* 47 */ "!text/double_9qm_rqm",
+ null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_rqm",
+ /* 53 */ "!text/double_9qm_rqm",
};
/* Language ne: Nepali */
@@ -2405,55 +2464,56 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0915: "क" DEVANAGARI LETTER KA
// U+0916: "ख" DEVANAGARI LETTER KHA
// U+0917: "ग" DEVANAGARI LETTER GA
- /* 45 */ "\u0915\u0916\u0917",
- /* 46~ */
+ /* 51 */ "\u0915\u0916\u0917",
+ /* 52~ */
null, null, null, null, null,
- /* ~50 */
+ /* ~56 */
// U+0930/U+0941/U+002E "रु." NEPALESE RUPEE SIGN
- /* 51 */ "\u0930\u0941.",
- /* 52~ */
+ /* 57 */ "\u0930\u0941.",
+ /* 58~ */
null, null, null, null, null, null, null, null, null, null, null,
- /* ~62 */
+ /* ~68 */
// U+0967: "१" DEVANAGARI DIGIT ONE
- /* 63 */ "\u0967",
+ /* 69 */ "\u0967",
// U+0968: "२" DEVANAGARI DIGIT TWO
- /* 64 */ "\u0968",
+ /* 70 */ "\u0968",
// U+0969: "३" DEVANAGARI DIGIT THREE
- /* 65 */ "\u0969",
+ /* 71 */ "\u0969",
// U+096A: "४" DEVANAGARI DIGIT FOUR
- /* 66 */ "\u096A",
+ /* 72 */ "\u096A",
// U+096B: "५" DEVANAGARI DIGIT FIVE
- /* 67 */ "\u096B",
+ /* 73 */ "\u096B",
// U+096C: "६" DEVANAGARI DIGIT SIX
- /* 68 */ "\u096C",
+ /* 74 */ "\u096C",
// U+096D: "७" DEVANAGARI DIGIT SEVEN
- /* 69 */ "\u096D",
+ /* 75 */ "\u096D",
// U+096E: "८" DEVANAGARI DIGIT EIGHT
- /* 70 */ "\u096E",
+ /* 76 */ "\u096E",
// U+096F: "९" DEVANAGARI DIGIT NINE
- /* 71 */ "\u096F",
+ /* 77 */ "\u096F",
// U+0966: "०" DEVANAGARI DIGIT ZERO
- /* 72 */ "\u0966",
+ /* 78 */ "\u0966",
// Label for "switch to symbols" key.
- /* 73 */ "?\u0967\u0968\u0969",
+ /* 79 */ "?\u0967\u0968\u0969",
// Label for "switch to symbols with microphone" key. This string shouldn't include the "mic"
// part because it'll be appended by the code.
- /* 74 */ "\u0967\u0968\u0969",
- /* 75 */ "1",
- /* 76 */ "2",
- /* 77 */ "3",
- /* 78 */ "4",
- /* 79 */ "5",
- /* 80 */ "6",
- /* 81 */ "7",
- /* 82 */ "8",
- /* 83 */ "9",
- /* 84 */ "0",
+ /* 80 */ "\u0967\u0968\u0969",
+ /* 81 */ "1",
+ /* 82 */ "2",
+ /* 83 */ "3",
+ /* 84 */ "4",
+ /* 85 */ "5",
+ /* 86 */ "6",
+ /* 87 */ "7",
+ /* 88 */ "8",
+ /* 89 */ "9",
+ /* 90 */ "0",
};
/* Language nl: Dutch */
@@ -2508,10 +2568,10 @@ public final class KeyboardTextsSet {
/* 9~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_rqm",
- /* 47 */ "!text/double_9qm_rqm",
+ null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_rqm",
+ /* 53 */ "!text/double_9qm_rqm",
};
/* Language pl: Polish */
@@ -2569,10 +2629,10 @@ public final class KeyboardTextsSet {
/* 15~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_rqm",
- /* 47 */ "!text/double_9qm_rqm",
+ null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_rqm",
+ /* 53 */ "!text/double_9qm_rqm",
};
/* Language pt: Portuguese */
@@ -2675,10 +2735,10 @@ public final class KeyboardTextsSet {
/* 12~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_rqm",
- /* 47 */ "!text/double_9qm_rqm",
+ null, null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_rqm",
+ /* 53 */ "!text/double_9qm_rqm",
};
/* Language ru: Russian */
@@ -2707,14 +2767,16 @@ public final class KeyboardTextsSet {
/* ~42 */
// U+0451: "ё" CYRILLIC SMALL LETTER IO
/* 43 */ "\u0451",
- /* 44 */ null,
+ /* 44~ */
+ null, null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
+ /* 51 */ "\u0410\u0411\u0412",
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
};
/* Language sk: Slovak */
@@ -2808,11 +2870,12 @@ public final class KeyboardTextsSet {
/* 16~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language sl: Slovenian */
@@ -2836,12 +2899,12 @@ public final class KeyboardTextsSet {
/* 13~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null,
- /* ~45 */
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null, null, null, null,
+ /* ~51 */
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language sr: Serbian */
@@ -2881,16 +2944,19 @@ public final class KeyboardTextsSet {
/* 43 */ "\u0450",
// U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
/* 44 */ "\u045D",
+ /* 45~ */
+ null, null, null, null, null, null,
+ /* ~50 */
// END: More keys definitions for Serbian (Cyrillic)
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ /* 51 */ "\u0410\u0411\u0412",
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language sv: Swedish */
@@ -2972,10 +3038,10 @@ public final class KeyboardTextsSet {
/* 24 */ "\u00E6",
/* 25~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null,
- /* ~47 */
- /* 48 */ "!text/single_raqm_laqm",
- /* 49 */ "!text/double_raqm_laqm",
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~53 */
+ /* 54 */ "!text/single_raqm_laqm",
+ /* 55 */ "!text/double_raqm_laqm",
};
/* Language sw: Swahili */
@@ -3035,17 +3101,18 @@ public final class KeyboardTextsSet {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0E01: "ก" THAI CHARACTER KO KAI
// U+0E02: "ข" THAI CHARACTER KHO KHAI
// U+0E04: "ค" THAI CHARACTER KHO KHWAI
- /* 45 */ "\u0E01\u0E02\u0E04",
- /* 46~ */
+ /* 51 */ "\u0E01\u0E02\u0E04",
+ /* 52~ */
null, null, null, null, null,
- /* ~50 */
+ /* ~56 */
// U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT
- /* 51 */ "\u0E3F",
+ /* 57 */ "\u0E3F",
};
/* Language tl: Tagalog */
@@ -3175,20 +3242,20 @@ public final class KeyboardTextsSet {
// U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN
/* 37 */ "\u044A",
/* 38~ */
- null, null, null, null, null, null, null,
- /* ~44 */
+ null, null, null, null, null, null, null, null, null, null, null, null, null,
+ /* ~50 */
// Label for "switch to alphabetic" key.
// U+0410: "А" CYRILLIC CAPITAL LETTER A
// U+0411: "Б" CYRILLIC CAPITAL LETTER BE
// U+0412: "В" CYRILLIC CAPITAL LETTER VE
- /* 45 */ "\u0410\u0411\u0412",
- /* 46 */ "!text/single_9qm_lqm",
- /* 47 */ "!text/double_9qm_lqm",
- /* 48~ */
+ /* 51 */ "\u0410\u0411\u0412",
+ /* 52 */ "!text/single_9qm_lqm",
+ /* 53 */ "!text/double_9qm_lqm",
+ /* 54~ */
null, null, null,
- /* ~50 */
+ /* ~56 */
// U+20B4: "₴" HRYVNIA SIGN
- /* 51 */ "\u20B4",
+ /* 57 */ "\u20B4",
};
/* Language vi: Vietnamese */
@@ -3273,10 +3340,11 @@ public final class KeyboardTextsSet {
/* 10~ */
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
- null, null, null, null, null, null, null, null, null, null, null,
- /* ~50 */
+ null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+ null, null,
+ /* ~56 */
// U+20AB: "₫" DONG SIGN
- /* 51 */ "\u20AB",
+ /* 57 */ "\u20AB",
};
/* Language zu: Zulu */
diff --git a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java b/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java
index 463d09344..d034515ca 100644
--- a/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java
+++ b/java/src/com/android/inputmethod/latin/AbstractDictionaryWriter.java
@@ -55,8 +55,7 @@ abstract public class AbstractDictionaryWriter extends Dictionary {
// TODO: Remove lastModifiedTime after making binary dictionary support forgetting curve.
abstract public void addBigramWords(final String word0, final String word1,
- final int frequency, final boolean isValid,
- final long lastModifiedTime);
+ final int frequency, final boolean isValid, final long lastModifiedTime);
abstract public void removeBigramWords(final String word0, final String word1);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 722a82961..ad94a0493 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -432,8 +432,9 @@ public final class BinaryDictionaryFileDumper {
// Actually copy the file
final byte[] buffer = new byte[FILE_READ_BUFFER_SIZE];
- for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer))
+ for (int readBytes = input.read(buffer); readBytes >= 0; readBytes = input.read(buffer)) {
output.write(buffer, 0, readBytes);
+ }
input.close();
}
@@ -478,8 +479,7 @@ public final class BinaryDictionaryFileDumper {
* @param context the context for resources and providers.
* @param clientId the client ID to use.
*/
- public static void initializeClientRecordHelper(final Context context,
- final String clientId) {
+ public static void initializeClientRecordHelper(final Context context, final String clientId) {
try {
final ContentProviderClient client = context.getContentResolver().
acquireContentProviderClient(getProviderUriBuilder("").build());
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index c4f96016c..9a9653094 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -174,6 +174,7 @@ public final class Constants {
public static final int CODE_SLASH = '/';
public static final int CODE_COMMERCIAL_AT = '@';
public static final int CODE_PLUS = '+';
+ public static final int CODE_PERCENT = '%';
public static final int CODE_CLOSING_PARENTHESIS = ')';
public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
public static final int CODE_CLOSING_CURLY_BRACKET = '}';
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index 8caf6f17f..fcf043031 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -52,8 +52,7 @@ public final class InputAttributes {
} else if (inputClass == 0) {
// TODO: is this check still necessary?
Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x"
- + " imeOptions=0x%08x",
- inputType, editorInfo.imeOptions));
+ + " imeOptions=0x%08x", inputType, editorInfo.imeOptions));
}
mIsSettingsSuggestionStripOn = false;
mInputTypeNoAutoCorrect = false;
@@ -204,8 +203,7 @@ public final class InputAttributes {
public static boolean inPrivateImeOptions(String packageName, String key,
EditorInfo editorInfo) {
if (editorInfo == null) return false;
- final String findingKey = (packageName != null) ? packageName + "." + key
- : key;
+ final String findingKey = (packageName != null) ? packageName + "." + key : key;
return StringUtils.containsInCommaSplittableText(findingKey, editorInfo.privateImeOptions);
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 608bb3cea..2e22af9f9 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -196,9 +196,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private int mLastSelectionStart = NOT_A_CURSOR_POSITION;
private int mLastSelectionEnd = NOT_A_CURSOR_POSITION;
- // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't
- // "expect" it, it means the user actually moved the cursor.
- private boolean mExpectingUpdateSelection;
private int mDeleteCount;
private long mLastKeyTime;
private final TreeSet<Long> mCurrentlyPressedHardwareKeys = CollectionUtils.newTreeSet();
@@ -761,8 +758,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
.findViewById(android.R.id.extractArea);
mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing);
mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view);
- if (mSuggestionStripView != null)
+ if (mSuggestionStripView != null) {
mSuggestionStripView.setListener(this, view);
+ }
if (LatinImeLogger.sVISUALDEBUG) {
mKeyPreviewBackingView.setBackgroundColor(0x10FF0000);
}
@@ -1081,16 +1079,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
+ ", ce=" + composingSpanEnd);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- final boolean expectingUpdateSelectionFromLogger =
- ResearchLogger.getAndClearLatinIMEExpectingUpdateSelection();
ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd,
oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart,
- composingSpanEnd, mExpectingUpdateSelection,
- expectingUpdateSelectionFromLogger, mConnection);
- if (expectingUpdateSelectionFromLogger) {
- // TODO: Investigate. Quitting now sounds wrong - we won't do the resetting work
- return;
- }
+ composingSpanEnd, mConnection);
}
final boolean selectionChanged = mLastSelectionStart != newSelStart
@@ -1109,14 +1100,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: revisit this when LatinIME supports hardware keyboards.
// NOTE: the test harness subclasses LatinIME and overrides isInputViewShown().
// TODO: find a better way to simulate actual execution.
- if (isInputViewShown() && !mExpectingUpdateSelection
- && !mConnection.isBelatedExpectedUpdate(oldSelStart, newSelStart)) {
- // TAKE CARE: there is a race condition when we enter this test even when the user
- // did not explicitly move the cursor. This happens when typing fast, where two keys
- // turn this flag on in succession and both onUpdateSelection() calls arrive after
- // the second one - the first call successfully avoids this test, but the second one
- // enters. For the moment we rely on noComposingSpan to further reduce the impact.
-
+ if (isInputViewShown() && !mConnection.isBelatedExpectedUpdate(oldSelStart, newSelStart)) {
// TODO: the following is probably better done in resetEntireInputState().
// it should only happen when the cursor moved, and the very purpose of the
// test below is to narrow down whether this happened or not. Likewise with
@@ -1161,7 +1145,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mRecapitalizeStatus.deactivate();
mKeyboardSwitcher.updateShiftState();
}
- mExpectingUpdateSelection = false;
// Make a note of the cursor position
mLastSelectionStart = newSelStart;
@@ -1347,8 +1330,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public boolean onEvaluateFullscreenMode() {
// Reread resource value here, because this method is called by framework anytime as needed.
- final boolean isFullscreenModeAllowed =
- Settings.readUseFullscreenMode(getResources());
+ final boolean isFullscreenModeAllowed = Settings.readUseFullscreenMode(getResources());
if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) {
// TODO: Remove this hack. Actually we should not really assume NO_EXTRACT_UI
// implies NO_FULLSCREEN. However, the framework mistakenly does. i.e. NO_EXTRACT_UI
@@ -1388,8 +1370,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void resetComposingState(final boolean alsoResetLastComposedWord) {
mWordComposer.reset();
- if (alsoResetLastComposedWord)
+ if (alsoResetLastComposedWord) {
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
+ }
}
private void commitTyped(final String separatorString) {
@@ -1436,15 +1419,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (0 != (auto & TextUtils.CAP_MODE_CHARACTERS)) {
return WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED;
}
- if (0 != auto) return WordComposer.CAPS_MODE_AUTO_SHIFTED;
+ if (0 != auto) {
+ return WordComposer.CAPS_MODE_AUTO_SHIFTED;
+ }
return WordComposer.CAPS_MODE_OFF;
}
private void swapSwapperAndSpace() {
final CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0);
// It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
- if (lastTwo != null && lastTwo.length() == 2
- && lastTwo.charAt(0) == Constants.CODE_SPACE) {
+ if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Constants.CODE_SPACE) {
mConnection.deleteSurroundingText(2, 0);
final String text = lastTwo.charAt(1) + " ";
mConnection.commitText(text, 1);
@@ -1502,6 +1486,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|| codePoint == Constants.CODE_CLOSING_CURLY_BRACKET
|| codePoint == Constants.CODE_CLOSING_ANGLE_BRACKET
|| codePoint == Constants.CODE_PLUS
+ || codePoint == Constants.CODE_PERCENT
|| Character.getType(codePoint) == Character.OTHER_SYMBOL;
}
@@ -1739,7 +1724,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
handleCharacter(primaryCode, keyX, keyY, spaceState);
}
- mExpectingUpdateSelection = true;
return didAutoCorrect;
}
@@ -1805,7 +1789,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
}
- mExpectingUpdateSelection = true;
}
final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
if (Character.isLetterOrDigit(codePointBeforeCursor)
@@ -1996,8 +1979,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This method must run in UI Thread.
public void onEndBatchInputAsyncInternal(final SuggestedWords suggestedWords) {
- final String batchInputText = suggestedWords.isEmpty()
- ? null : suggestedWords.getWord(0);
+ final String batchInputText = suggestedWords.isEmpty() ? null : suggestedWords.getWord(0);
if (TextUtils.isEmpty(batchInputText)) {
return;
}
@@ -2019,7 +2001,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mWordComposer.setBatchInputWord(batchInputText);
mConnection.setComposingText(batchInputText, 1);
}
- mExpectingUpdateSelection = true;
mConnection.endBatchEdit();
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_onEndBatchInput(batchInputText, 0, suggestedWords);
@@ -2073,9 +2054,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void handleBackspace(final int spaceState) {
- // We revert these in this method if the deletion doesn't happen.
mDeleteCount++;
- mExpectingUpdateSelection = true;
// In many cases, we may have to put the keyboard in auto-shift state again. However
// we want to wait a few milliseconds before doing it to avoid the keyboard flashing
@@ -2168,10 +2147,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
if (codePointBeforeCursor == Constants.NOT_A_CODE) {
- // Nothing to delete before the cursor. We have to revert the deletion states
- // that were updated at the beginning of this method.
- mDeleteCount--;
- mExpectingUpdateSelection = false;
+ // Nothing to delete before the cursor.
return;
}
final int lengthToDelete =
@@ -2219,8 +2195,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
/*
* Strip a trailing space if necessary and returns whether it's a swap weak space situation.
*/
- private boolean maybeStripSpace(final int code,
- final int spaceState, final boolean isFromSuggestionStrip) {
+ private boolean maybeStripSpace(final int code, final int spaceState,
+ final boolean isFromSuggestionStrip) {
if (Constants.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
mConnection.removeTrailingSpace();
return false;
@@ -2235,8 +2211,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return false;
}
- private void handleCharacter(final int primaryCode, final int x,
- final int y, final int spaceState) {
+ private void handleCharacter(final int primaryCode, final int x, final int y,
+ final int spaceState) {
// TODO: refactor this method to stop flipping isComposingWord around all the time, and
// make it shorter (possibly cut into several pieces). Also factor handleNonSpecialCharacter
// which has the same name as other handle* methods but is not the same.
@@ -2303,8 +2279,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
} else {
- final boolean swapWeakSpace = maybeStripSpace(primaryCode,
- spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x);
+ final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
+ Constants.SUGGESTION_STRIP_COORDINATE == x);
sendKeyCodePoint(primaryCode);
@@ -2342,9 +2318,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
mLastSelectionStart = mRecapitalizeStatus.getNewCursorStart();
mLastSelectionEnd = mRecapitalizeStatus.getNewCursorEnd();
- mConnection.setSelection(mLastSelectionStart, mLastSelectionEnd);
}
}
+ mConnection.finishComposingText();
mRecapitalizeStatus.rotate();
final int numCharsDeleted = mLastSelectionEnd - mLastSelectionStart;
mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
@@ -2541,6 +2517,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
+ private String getPreviousWordForSuggestion(final SettingsValues currentSettings) {
+ if (currentSettings.mCurrentLanguageHasSpaces) {
+ // If we are typing in a language with spaces we can just look up the previous
+ // word from textview.
+ return mConnection.getNthPreviousWord(currentSettings.mWordSeparators,
+ mWordComposer.isComposingWord() ? 2 : 1);
+ } else {
+ return LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ? null
+ : mLastComposedWord.mCommittedWord;
+ }
+ }
+
private void getSuggestedWords(final int sessionId, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
@@ -2554,16 +2542,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// should just skip whitespace if any, so 1.
final SettingsValues currentSettings = mSettings.getCurrent();
final int[] additionalFeaturesOptions = currentSettings.mAdditionalFeaturesSettingValues;
- final String prevWord;
- if (currentSettings.mCurrentLanguageHasSpaces) {
- // If we are typing in a language with spaces we can just look up the previous
- // word from textview.
- prevWord = mConnection.getNthPreviousWord(currentSettings.mWordSeparators,
- mWordComposer.isComposingWord() ? 2 : 1);
- } else {
- prevWord = LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ? null
- : mLastComposedWord.mCommittedWord;
- }
+ final String prevWord = getPreviousWordForSuggestion(currentSettings);
suggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(),
currentSettings.mBlockPotentiallyOffensive, currentSettings.mCorrectionEnabled,
additionalFeaturesOptions, sessionId, sequenceNumber, callback);
@@ -2681,7 +2660,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
ResearchLogger.latinIme_commitCurrentAutoCorrection(typedWord, autoCorrection,
separator, mWordComposer.isBatchMode(), suggestedWords);
}
- mExpectingUpdateSelection = true;
commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD,
separator);
if (!typedWord.equals(autoCorrection)) {
@@ -2752,7 +2730,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// typed word.
final String replacedWord = mWordComposer.getTypedWord();
LatinImeLogger.logOnManualSuggestion(replacedWord, suggestion, index, suggestedWords);
- mExpectingUpdateSelection = true;
commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
LastComposedWord.NOT_A_SEPARATOR);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@@ -3026,8 +3003,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
throw new RuntimeException("revertCommit, but we are composing a word");
}
final CharSequence wordBeforeCursor =
- mConnection.getTextBeforeCursor(deleteLength, 0)
- .subSequence(0, cancelLength);
+ mConnection.getTextBeforeCursor(deleteLength, 0).subSequence(0, cancelLength);
if (!TextUtils.equals(committedWord, wordBeforeCursor)) {
throw new RuntimeException("revertCommit check failed: we thought we were "
+ "reverting \"" + committedWord
@@ -3228,8 +3204,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
mRichImm.getInputMethodIdOfThisIme(),
Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
break;
case 1:
@@ -3238,9 +3214,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
};
- final AlertDialog.Builder builder = new AlertDialog.Builder(this)
- .setItems(items, listener)
- .setTitle(title);
+ final AlertDialog.Builder builder =
+ new AlertDialog.Builder(this).setItems(items, listener).setTitle(title);
showOptionDialog(builder.create());
}
@@ -3305,7 +3280,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1;
p.println(" Keyboard mode = " + keyboardMode);
final SettingsValues settingsValues = mSettings.getCurrent();
- p.println(" mIsSuggestionsSuggestionsRequested = "
+ p.println(" mIsSuggestionsRequested = "
+ settingsValues.isSuggestionsRequested(mDisplayOrientation));
p.println(" mCorrectionEnabled=" + settingsValues.mCorrectionEnabled);
p.println(" isComposingWord=" + mWordComposer.isComposingWord());
diff --git a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
index 9f7f502ea..fda97dafc 100644
--- a/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/AbstractDictDecoder.java
@@ -60,7 +60,8 @@ public abstract class AbstractDictDecoder implements DictDecoder {
0 != (optionsFlags & FormatSpec.GERMAN_UMLAUT_PROCESSING_FLAG),
0 != (optionsFlags & FormatSpec.FRENCH_LIGATURE_PROCESSING_FLAG)),
new FormatOptions(version,
- 0 != (optionsFlags & FormatSpec.SUPPORTS_DYNAMIC_UPDATE)));
+ 0 != (optionsFlags & FormatSpec.SUPPORTS_DYNAMIC_UPDATE),
+ 0 != (optionsFlags & FormatSpec.CONTAINS_TIMESTAMP_FLAG)));
return header;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 216492b4d..8a8ceaa8c 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -169,6 +169,14 @@ public final class BinaryDictDecoderUtils {
return size;
}
+ static int getCharArraySize(final int[] chars, final int start, final int end) {
+ int size = 0;
+ for (int i = start; i < end; ++i) {
+ size += getCharSize(chars[i]);
+ }
+ return size;
+ }
+
/**
* Writes a char array to a byte buffer.
*
@@ -200,8 +208,7 @@ public final class BinaryDictDecoderUtils {
* @param word the string to write.
* @return the size written, in bytes.
*/
- static int writeString(final byte[] buffer, final int origin,
- final String word) {
+ static int writeString(final byte[] buffer, final int origin, final String word) {
final int length = word.length();
int index = origin;
for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
@@ -223,22 +230,62 @@ public final class BinaryDictDecoderUtils {
*
* This will also write the terminator byte.
*
- * @param buffer the OutputStream to write to.
+ * @param stream the OutputStream to write to.
* @param word the string to write.
+ * @return the size written, in bytes.
*/
- static void writeString(final OutputStream buffer, final String word) throws IOException {
+ static int writeString(final OutputStream stream, final String word) throws IOException {
final int length = word.length();
+ int written = 0;
for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
final int codePoint = word.codePointAt(i);
- if (1 == getCharSize(codePoint)) {
- buffer.write((byte) codePoint);
+ final int charSize = getCharSize(codePoint);
+ if (1 == charSize) {
+ stream.write((byte) codePoint);
} else {
- buffer.write((byte) (0xFF & (codePoint >> 16)));
- buffer.write((byte) (0xFF & (codePoint >> 8)));
- buffer.write((byte) (0xFF & codePoint));
+ stream.write((byte) (0xFF & (codePoint >> 16)));
+ stream.write((byte) (0xFF & (codePoint >> 8)));
+ stream.write((byte) (0xFF & codePoint));
}
+ written += charSize;
+ }
+ stream.write(FormatSpec.PTNODE_CHARACTERS_TERMINATOR);
+ written += FormatSpec.PTNODE_TERMINATOR_SIZE;
+ return written;
+ }
+
+ /**
+ * Writes an array of code points with our character format to an OutputStream.
+ *
+ * This will also write the terminator byte.
+ *
+ * @param stream the OutputStream to write to.
+ * @param codePoints the array of code points
+ * @return the size written, in bytes.
+ */
+ // TODO: Merge this method with writeCharArray and rename the various write* methods to
+ // make the difference clear.
+ static int writeCodePoints(final OutputStream stream, final int[] codePoints,
+ final int startIndex, final int endIndex)
+ throws IOException {
+ int written = 0;
+ for (int i = startIndex; i < endIndex; ++i) {
+ final int codePoint = codePoints[i];
+ final int charSize = getCharSize(codePoint);
+ if (1 == charSize) {
+ stream.write((byte) codePoint);
+ } else {
+ stream.write((byte) (0xFF & (codePoint >> 16)));
+ stream.write((byte) (0xFF & (codePoint >> 8)));
+ stream.write((byte) (0xFF & codePoint));
+ }
+ written += charSize;
+ }
+ if (endIndex - startIndex > 1) {
+ stream.write(FormatSpec.PTNODE_CHARACTERS_TERMINATOR);
+ written += FormatSpec.PTNODE_TERMINATOR_SIZE;
}
- buffer.write(FormatSpec.PTNODE_CHARACTERS_TERMINATOR);
+ return written;
}
/**
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index f761829de..bc1a2579e 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
+import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
@@ -245,6 +246,26 @@ public class BinaryDictEncoderUtils {
}
}
+ static void writeUIntToDictBuffer(final DictBuffer dictBuffer, final int value,
+ final int size) {
+ switch(size) {
+ case 4:
+ dictBuffer.put((byte) ((value >> 24) & 0xFF));
+ /* fall through */
+ case 3:
+ dictBuffer.put((byte) ((value >> 16) & 0xFF));
+ /* fall through */
+ case 2:
+ dictBuffer.put((byte) ((value >> 8) & 0xFF));
+ /* fall through */
+ case 1:
+ dictBuffer.put((byte) (value & 0xFF));
+ break;
+ default:
+ /* nop */
+ }
+ }
+
// End utility methods
// This method is responsible for finding a nice ordering of the nodes that favors run-time
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 0f7d2f6c9..8d14e4d60 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -245,8 +245,7 @@ public final class BinaryDictIOUtils {
/**
* @return the size written, in bytes. Always 3 bytes.
*/
- static int writeSInt24ToBuffer(final DictBuffer dictBuffer,
- final int value) {
+ static int writeSInt24ToBuffer(final DictBuffer dictBuffer, final int value) {
final int absValue = Math.abs(value);
dictBuffer.put((byte)(((value < 0 ? 0x80 : 0) | (absValue >> 16)) & 0xFF));
dictBuffer.put((byte)((absValue >> 8) & 0xFF));
@@ -301,35 +300,6 @@ public final class BinaryDictIOUtils {
}
/**
- * Write a string to a stream.
- *
- * @param destination the stream to write.
- * @param word the string to be written.
- * @return the size written, in bytes.
- * @throws IOException
- */
- private static int writeString(final OutputStream destination, final String word)
- throws IOException {
- int size = 0;
- final int length = word.length();
- for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
- final int codePoint = word.codePointAt(i);
- if (CharEncoding.getCharSize(codePoint) == 1) {
- destination.write((byte)codePoint);
- size++;
- } else {
- destination.write((byte)(0xFF & (codePoint >> 16)));
- destination.write((byte)(0xFF & (codePoint >> 8)));
- destination.write((byte)(0xFF & codePoint));
- size += 3;
- }
- }
- destination.write((byte)FormatSpec.PTNODE_CHARACTERS_TERMINATOR);
- size += FormatSpec.PTNODE_TERMINATOR_SIZE;
- return size;
- }
-
- /**
* Write a PtNode to an output stream from a PtNodeInfo.
* A PtNode is an in-memory representation of a node in the patricia trie.
* A PtNode info is a container for low-level information about how the
@@ -387,7 +357,7 @@ public final class BinaryDictIOUtils {
destination.write((byte)BinaryDictEncoderUtils.makeShortcutFlags(
shortcutIterator.hasNext(), target.mFrequency));
size++;
- size += writeString(destination, target.mWord);
+ size += CharEncoding.writeString(destination, target.mWord);
}
}
@@ -445,6 +415,25 @@ public final class BinaryDictIOUtils {
}
/**
+ * Writes a PtNodeCount to the stream.
+ *
+ * @param destination the stream to write.
+ * @param ptNodeCount the count.
+ * @return the size written in bytes.
+ */
+ static int writePtNodeCount(final OutputStream destination, final int ptNodeCount)
+ throws IOException {
+ final int countSize = BinaryDictIOUtils.getPtNodeCountSize(ptNodeCount);
+ // the count must fit on one byte or two bytes.
+ // Please see comments in FormatSpec.
+ if (countSize != 1 && countSize != 2) {
+ throw new RuntimeException("Strange size from getPtNodeCountSize : " + countSize);
+ }
+ BinaryDictEncoderUtils.writeUIntToStream(destination, ptNodeCount, countSize);
+ return countSize;
+ }
+
+ /**
* Write a node array to the stream.
*
* @param destination the stream to write.
@@ -454,18 +443,7 @@ public final class BinaryDictIOUtils {
*/
static int writeNodes(final OutputStream destination, final PtNodeInfo[] infos)
throws IOException {
- int size = getPtNodeCountSize(infos.length);
- switch (getPtNodeCountSize(infos.length)) {
- case 1:
- destination.write((byte)infos.length);
- break;
- case 2:
- destination.write((byte)(infos.length >> 8));
- destination.write((byte)(infos.length & 0xFF));
- break;
- default:
- throw new RuntimeException("Invalid node count size.");
- }
+ int size = writePtNodeCount(destination, infos.length);
for (final PtNodeInfo info : infos) size += writePtNode(destination, info);
writeSInt24ToStream(destination, FormatSpec.NO_FORWARD_LINK_ADDRESS);
return size + FormatSpec.FORWARD_LINK_ADDRESS_SIZE;
diff --git a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
index 3dbeee099..91543986d 100644
--- a/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/DictDecoder.java
@@ -35,6 +35,7 @@ import java.util.TreeMap;
/**
* An interface of binary dictionary decoders.
*/
+// TODO: Straighten out responsibility for the buffer's file pointer.
public interface DictDecoder {
/**
@@ -43,7 +44,7 @@ public interface DictDecoder {
public FileHeader readHeader() throws IOException, UnsupportedFormatException;
/**
- * Reads PtNode from nodeAddress.
+ * Reads PtNode from ptNodePos.
* @param ptNodePos the position of PtNode.
* @param formatOptions the format options.
* @return PtNodeInfo.
diff --git a/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java
index 336277196..971b4ff9f 100644
--- a/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java
@@ -22,6 +22,7 @@ import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+import com.android.inputmethod.latin.utils.CollectionUtils;
import java.io.IOException;
import java.io.OutputStream;
@@ -36,7 +37,7 @@ import java.util.Arrays;
@UsedForTesting
public final class DynamicBinaryDictIOUtils {
private static final boolean DBG = false;
- private static final int MAX_JUMPS = 10000;
+ static final int MAX_JUMPS = 10000;
private DynamicBinaryDictIOUtils() {
// This utility class is not publicly instantiable.
@@ -217,6 +218,25 @@ public final class DynamicBinaryDictIOUtils {
}
/**
+ * Converts a list of WeightedString to a list of PendingAttribute.
+ */
+ public static ArrayList<PendingAttribute> resolveBigramPositions(final DictUpdater dictUpdater,
+ final ArrayList<WeightedString> bigramStrings)
+ throws IOException, UnsupportedFormatException {
+ if (bigramStrings == null) return CollectionUtils.newArrayList();
+ final ArrayList<PendingAttribute> bigrams = CollectionUtils.newArrayList();
+ for (final WeightedString bigram : bigramStrings) {
+ final int pos = dictUpdater.getTerminalPosition(bigram.mWord);
+ if (pos == FormatSpec.NOT_VALID_WORD) {
+ // TODO: figure out what is the correct thing to do here.
+ } else {
+ bigrams.add(new PendingAttribute(bigram.mFrequency, pos));
+ }
+ }
+ return bigrams;
+ }
+
+ /**
* Insert a word into a binary dictionary.
*
* @param dictUpdater the dict updater.
@@ -238,18 +258,9 @@ public final class DynamicBinaryDictIOUtils {
final ArrayList<WeightedString> shortcuts, final boolean isNotAWord,
final boolean isBlackListEntry)
throws IOException, UnsupportedFormatException {
- final ArrayList<PendingAttribute> bigrams = new ArrayList<PendingAttribute>();
+ final ArrayList<PendingAttribute> bigrams = resolveBigramPositions(dictUpdater,
+ bigramStrings);
final DictBuffer dictBuffer = dictUpdater.getDictBuffer();
- if (bigramStrings != null) {
- for (final WeightedString bigram : bigramStrings) {
- int position = dictUpdater.getTerminalPosition(bigram.mWord);
- if (position == FormatSpec.NOT_VALID_WORD) {
- // TODO: figure out what is the correct thing to do here.
- } else {
- bigrams.add(new PendingAttribute(bigram.mFrequency, position));
- }
- }
- }
final boolean isTerminal = true;
final boolean hasBigrams = !bigrams.isEmpty();
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index 5a5d7af6b..b99aca2c8 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -37,13 +37,15 @@ public final class FormatSpec {
* sion
*
* o |
- * p | not used 4 bits
- * t | has bigrams ? 1 bit, 1 = yes, 0 = no : CONTAINS_BIGRAMS_FLAG
- * i | FRENCH_LIGATURE_PROCESSING_FLAG
- * o | supports dynamic updates ? 1 bit, 1 = yes, 0 = no : SUPPORTS_DYNAMIC_UPDATE
- * n | GERMAN_UMLAUT_PROCESSING_FLAG
- * f |
- * lags
+ * p | not used 3 bits
+ * t | each unigram and bigram entry has a time stamp?
+ * i | 1 bit, 1 = yes, 0 = no : CONTAINS_TIMESTAMP_FLAG
+ * o | has bigrams ? 1 bit, 1 = yes, 0 = no : CONTAINS_BIGRAMS_FLAG
+ * n | FRENCH_LIGATURE_PROCESSING_FLAG
+ * f | supports dynamic updates ? 1 bit, 1 = yes, 0 = no : SUPPORTS_DYNAMIC_UPDATE
+ * l | GERMAN_UMLAUT_PROCESSING_FLAG
+ * a |
+ * gs
*
* h |
* e | size of the file header, 4bytes
@@ -211,6 +213,7 @@ public final class FormatSpec {
static final int SUPPORTS_DYNAMIC_UPDATE = 0x2;
static final int FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
static final int CONTAINS_BIGRAMS_FLAG = 0x8;
+ static final int CONTAINS_TIMESTAMP_FLAG = 0x10;
// TODO: Make this value adaptative to content data, store it in the header, and
// use it in the reading code.
@@ -263,6 +266,7 @@ public final class FormatSpec {
// These values are used only by version 4 or later.
static final String TRIE_FILE_EXTENSION = ".trie";
static final String FREQ_FILE_EXTENSION = ".freq";
+ static final String UNIGRAM_TIMESTAMP_FILE_EXTENSION = ".timestamp";
// tat = Terminal Address Table
static final String TERMINAL_ADDRESS_TABLE_FILE_EXTENSION = ".tat";
static final String BIGRAM_FILE_EXTENSION = ".bigram";
@@ -271,19 +275,25 @@ public final class FormatSpec {
static final String CONTENT_TABLE_FILE_SUFFIX = "_index";
static final int FREQUENCY_AND_FLAGS_SIZE = 2;
static final int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
+ static final int UNIGRAM_TIMESTAMP_SIZE = 4;
// With the English main dictionary as of October 2013, the size of bigram address table is
- // is 584KB with the block size being 4.
- // This is 91% of that of full address table.
- static final int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 4;
- static final int BIGRAM_CONTENT_COUNT = 1;
+ // is 345KB with the block size being 16.
+ // This is 54% of that of full address table.
+ static final int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16;
+ static final int BIGRAM_CONTENT_COUNT = 2;
static final int BIGRAM_FREQ_CONTENT_INDEX = 0;
+ static final int BIGRAM_TIMESTAMP_CONTENT_INDEX = 1;
static final String BIGRAM_FREQ_CONTENT_ID = "_freq";
+ static final String BIGRAM_TIMESTAMP_CONTENT_ID = "_timestamp";
+ static final int BIGRAM_TIMESTAMP_SIZE = 4;
+ static final int BIGRAM_COUNTER_SIZE = 1;
+ static final int BIGRAM_LEVEL_SIZE = 1;
static final int SHORTCUT_CONTENT_COUNT = 1;
static final int SHORTCUT_CONTENT_INDEX = 0;
// With the English main dictionary as of October 2013, the size of shortcut address table is
- // 29KB with the block size being 64.
+ // 26KB with the block size being 64.
// This is only 4.4% of that of full address table.
static final int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
static final String SHORTCUT_CONTENT_ID = "_shortcut";
@@ -321,6 +331,7 @@ public final class FormatSpec {
public final int mVersion;
public final boolean mSupportsDynamicUpdate;
public final boolean mHasTerminalId;
+ public final boolean mHasTimestamp;
@UsedForTesting
public FormatOptions(final int version) {
this(version, false);
@@ -328,6 +339,11 @@ public final class FormatSpec {
@UsedForTesting
public FormatOptions(final int version, final boolean supportsDynamicUpdate) {
+ this(version, supportsDynamicUpdate, false /* hasTimestamp */);
+ }
+
+ public FormatOptions(final int version, final boolean supportsDynamicUpdate,
+ final boolean hasTimestamp) {
mVersion = version;
if (version < FIRST_VERSION_WITH_DYNAMIC_UPDATE && supportsDynamicUpdate) {
throw new RuntimeException("Dynamic updates are only supported with versions "
@@ -335,6 +351,7 @@ public final class FormatSpec {
}
mSupportsDynamicUpdate = supportsDynamicUpdate;
mHasTerminalId = (version >= FIRST_VERSION_WITH_TERMINAL_ID);
+ mHasTimestamp = hasTimestamp;
}
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentReader.java b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentReader.java
new file mode 100644
index 000000000..06088b651
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentReader.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
+import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * An auxiliary class for reading SparseTable and data written by SparseTableContentWriter.
+ */
+public class SparseTableContentReader {
+
+ /**
+ * An interface of a function which is passed to SparseTableContentReader.read.
+ */
+ public interface SparseTableContentReaderInterface {
+ /**
+ * Reads data.
+ *
+ * @param buffer the DictBuffer. The position of the buffer is set to the head of data.
+ */
+ public void read(final DictBuffer buffer);
+ }
+
+ protected final int mContentCount;
+ protected final int mBlockSize;
+ protected final File mBaseDir;
+ protected final File mLookupTableFile;
+ protected final File[] mAddressTableFiles;
+ protected final File[] mContentFiles;
+ protected DictBuffer mLookupTableBuffer;
+ protected final DictBuffer[] mAddressTableBuffers;
+ private final DictBuffer[] mContentBuffers;
+ protected final DictionaryBufferFactory mFactory;
+
+ /**
+ * Sole constructor of SparseTableContentReader.
+ *
+ * @param name the name of SparseTable.
+ * @param blockSize the block size of the content table.
+ * @param baseDir the directory which contains the files of the content table.
+ * @param contentFilenames the file names of content files.
+ * @param contentIds the ids of contents. These ids are used for a suffix of a name of
+ * address files and content files.
+ * @param factory the DictionaryBufferFactory which is used for opening the files.
+ */
+ public SparseTableContentReader(final String name, final int blockSize, final File baseDir,
+ final String[] contentFilenames, final String[] contentIds,
+ final DictionaryBufferFactory factory) {
+ if (contentFilenames.length != contentIds.length) {
+ throw new RuntimeException("The length of contentFilenames and the length of"
+ + " contentIds are different " + contentFilenames.length + ", "
+ + contentIds.length);
+ }
+ mBlockSize = blockSize;
+ mBaseDir = baseDir;
+ mFactory = factory;
+ mContentCount = contentFilenames.length;
+ mLookupTableFile = new File(baseDir, name + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX);
+ mAddressTableFiles = new File[mContentCount];
+ mContentFiles = new File[mContentCount];
+ for (int i = 0; i < mContentCount; ++i) {
+ mAddressTableFiles[i] = new File(mBaseDir,
+ name + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + contentIds[i]);
+ mContentFiles[i] = new File(mBaseDir, contentFilenames[i] + contentIds[i]);
+ }
+ mAddressTableBuffers = new DictBuffer[mContentCount];
+ mContentBuffers = new DictBuffer[mContentCount];
+ }
+
+ public void openBuffers() throws FileNotFoundException, IOException {
+ mLookupTableBuffer = mFactory.getDictionaryBuffer(mLookupTableFile);
+ for (int i = 0; i < mContentCount; ++i) {
+ mAddressTableBuffers[i] = mFactory.getDictionaryBuffer(mAddressTableFiles[i]);
+ mContentBuffers[i] = mFactory.getDictionaryBuffer(mContentFiles[i]);
+ }
+ }
+
+ protected void read(final int contentIndex, final int index,
+ final SparseTableContentReaderInterface reader) {
+ if (index < 0 || (index / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES
+ >= mLookupTableBuffer.limit()) {
+ return;
+ }
+
+ mLookupTableBuffer.position((index / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES);
+ final int posInAddressTable = mLookupTableBuffer.readInt();
+ if (posInAddressTable == SparseTable.NOT_EXIST) {
+ return;
+ }
+
+ mAddressTableBuffers[contentIndex].position(
+ (posInAddressTable + index % mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES);
+ final int address = mAddressTableBuffers[contentIndex].readInt();
+ if (address == SparseTable.NOT_EXIST) {
+ return;
+ }
+
+ mContentBuffers[contentIndex].position(address);
+ reader.read(mContentBuffers[contentIndex]);
+ }
+} \ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentUpdater.java b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentUpdater.java
new file mode 100644
index 000000000..4518f21b9
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentUpdater.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An auxiliary class for updating data associated with SparseTable.
+ */
+public class SparseTableContentUpdater extends SparseTableContentReader {
+ protected OutputStream mLookupTableOutStream;
+ protected OutputStream[] mAddressTableOutStreams;
+ protected OutputStream[] mContentOutStreams;
+
+ public SparseTableContentUpdater(final String name, final int blockSize,
+ final File baseDir, final String[] contentFilenames, final String[] contentIds,
+ final DictionaryBufferFactory factory) {
+ super(name, blockSize, baseDir, contentFilenames, contentIds, factory);
+ mAddressTableOutStreams = new OutputStream[mContentCount];
+ mContentOutStreams = new OutputStream[mContentCount];
+ }
+
+ protected void openStreamsAndBuffers() throws IOException {
+ openBuffers();
+ mLookupTableOutStream = new FileOutputStream(mLookupTableFile, true /* append */);
+ for (int i = 0; i < mContentCount; ++i) {
+ mAddressTableOutStreams[i] = new FileOutputStream(mAddressTableFiles[i],
+ true /* append */);
+ mContentOutStreams[i] = new FileOutputStream(mContentFiles[i], true /* append */);
+ }
+ }
+
+ /**
+ * Set the contentIndex-th elements of contentId-th table.
+ *
+ * @param contentId the id of the content table.
+ * @param contentIndex the index where to set the valie.
+ * @param value the value to set.
+ */
+ protected void setContentValue(final int contentId, final int contentIndex, final int value)
+ throws IOException {
+ if ((contentIndex / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES
+ >= mLookupTableBuffer.limit()) {
+ // Need to extend the lookup table
+ final int currentSize = mLookupTableBuffer.limit()
+ / SparseTable.SIZE_OF_INT_IN_BYTES;
+ final int target = contentIndex / mBlockSize + 1;
+ for (int i = currentSize; i < target; ++i) {
+ BinaryDictEncoderUtils.writeUIntToStream(mLookupTableOutStream,
+ SparseTable.NOT_EXIST, SparseTable.SIZE_OF_INT_IN_BYTES);
+ }
+ // We need to reopen the byte buffer of the lookup table because a MappedByteBuffer in
+ // Java isn't expanded automatically when the underlying file is expanded.
+ reopenLookupTable();
+ }
+
+ mLookupTableBuffer.position((contentIndex / mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES);
+ int posInAddressTable = mLookupTableBuffer.readInt();
+ if (posInAddressTable == SparseTable.NOT_EXIST) {
+ // Need to extend the address table
+ mLookupTableBuffer.position(mLookupTableBuffer.position()
+ - SparseTable.SIZE_OF_INT_IN_BYTES);
+ posInAddressTable = mAddressTableBuffers[0].limit() / mBlockSize;
+ BinaryDictEncoderUtils.writeUIntToDictBuffer(mLookupTableBuffer,
+ posInAddressTable, SparseTable.SIZE_OF_INT_IN_BYTES);
+ for (int i = 0; i < mContentCount; ++i) {
+ for (int j = 0; j < mBlockSize; ++j) {
+ BinaryDictEncoderUtils.writeUIntToStream(mAddressTableOutStreams[i],
+ SparseTable.NOT_EXIST, SparseTable.SIZE_OF_INT_IN_BYTES);
+ }
+ }
+ // We need to reopen the byte buffers of the address tables because a MappedByteBuffer
+ // in Java isn't expanded automatically when the underlying file is expanded.
+ reopenAddressTables();
+ }
+ posInAddressTable += (contentIndex % mBlockSize) * SparseTable.SIZE_OF_INT_IN_BYTES;
+
+ mAddressTableBuffers[contentId].position(posInAddressTable);
+ BinaryDictEncoderUtils.writeUIntToDictBuffer(mAddressTableBuffers[contentId],
+ value, SparseTable.SIZE_OF_INT_IN_BYTES);
+ }
+
+ private void reopenLookupTable() throws IOException {
+ mLookupTableOutStream.flush();
+ mLookupTableBuffer = mFactory.getDictionaryBuffer(mLookupTableFile);
+ }
+
+ private void reopenAddressTables() throws IOException {
+ for (int i = 0; i < mContentCount; ++i) {
+ mAddressTableOutStreams[i].flush();
+ mAddressTableBuffers[i] = mFactory.getDictionaryBuffer(mAddressTableFiles[i]);
+ }
+ }
+
+ protected void close() throws IOException {
+ mLookupTableOutStream.close();
+ for (final OutputStream stream : mAddressTableOutStreams) {
+ stream.close();
+ }
+ for (final OutputStream stream : mContentOutStreams) {
+ stream.close();
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/SparseTableContentWriter.java b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentWriter.java
new file mode 100644
index 000000000..49f0fd624
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/SparseTableContentWriter.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An auxiliary class for writing data associated with SparseTable to files.
+ */
+public class SparseTableContentWriter {
+ public interface SparseTableContentWriterInterface {
+ public void write(final OutputStream outStream) throws IOException;
+ }
+
+ private final int mContentCount;
+ private final SparseTable mSparseTable;
+ private final File mLookupTableFile;
+ protected final File mBaseDir;
+ private final File[] mAddressTableFiles;
+ private final File[] mContentFiles;
+ protected final OutputStream[] mContentOutStreams;
+
+ /**
+ * Sole constructor of SparseTableContentWriter.
+ *
+ * @param name the name of SparseTable.
+ * @param initialCapacity the initial capacity of SparseTable.
+ * @param blockSize the block size of the content table.
+ * @param baseDir the directory which contains the files of the content table.
+ * @param contentFilenames the file names of content files.
+ * @param contentIds the ids of contents. These ids are used for a suffix of a name of address
+ * files and content files.
+ */
+ public SparseTableContentWriter(final String name, final int initialCapacity,
+ final int blockSize, final File baseDir, final String[] contentFilenames,
+ final String[] contentIds) {
+ if (contentFilenames.length != contentIds.length) {
+ throw new RuntimeException("The length of contentFilenames and the length of"
+ + " contentIds are different " + contentFilenames.length + ", "
+ + contentIds.length);
+ }
+ mContentCount = contentFilenames.length;
+ mSparseTable = new SparseTable(initialCapacity, blockSize, mContentCount);
+ mLookupTableFile = new File(baseDir, name + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX);
+ mAddressTableFiles = new File[mContentCount];
+ mContentFiles = new File[mContentCount];
+ mBaseDir = baseDir;
+ for (int i = 0; i < mContentCount; ++i) {
+ mAddressTableFiles[i] = new File(mBaseDir,
+ name + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + contentIds[i]);
+ mContentFiles[i] = new File(mBaseDir, contentFilenames[i] + contentIds[i]);
+ }
+ mContentOutStreams = new OutputStream[mContentCount];
+ }
+
+ public void openStreams() throws FileNotFoundException {
+ for (int i = 0; i < mContentCount; ++i) {
+ mContentOutStreams[i] = new FileOutputStream(mContentFiles[i]);
+ }
+ }
+
+ protected void write(final int contentIndex, final int index,
+ final SparseTableContentWriterInterface writer) throws IOException {
+ mSparseTable.set(contentIndex, index, (int) mContentFiles[contentIndex].length());
+ writer.write(mContentOutStreams[contentIndex]);
+ mContentOutStreams[contentIndex].flush();
+ }
+
+ public void closeStreams() throws IOException {
+ mSparseTable.writeToFiles(mLookupTableFile, mAddressTableFiles);
+ for (int i = 0; i < mContentCount; ++i) {
+ mContentOutStreams[i].close();
+ }
+ }
+} \ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 53729075f..f0fed3fda 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -40,21 +40,45 @@ import java.util.Arrays;
public class Ver4DictDecoder extends AbstractDictDecoder {
private static final String TAG = Ver4DictDecoder.class.getSimpleName();
- private static final int FILETYPE_TRIE = 1;
- private static final int FILETYPE_FREQUENCY = 2;
- private static final int FILETYPE_TERMINAL_ADDRESS_TABLE = 3;
- private static final int FILETYPE_BIGRAM_FREQ = 4;
- private static final int FILETYPE_SHORTCUT = 5;
-
- private final File mDictDirectory;
- private final DictionaryBufferFactory mBufferFactory;
+ protected static final int FILETYPE_TRIE = 1;
+ protected static final int FILETYPE_FREQUENCY = 2;
+ protected static final int FILETYPE_TERMINAL_ADDRESS_TABLE = 3;
+ protected static final int FILETYPE_BIGRAM_FREQ = 4;
+ protected static final int FILETYPE_SHORTCUT = 5;
+
+ protected final File mDictDirectory;
+ protected final DictionaryBufferFactory mBufferFactory;
protected DictBuffer mDictBuffer;
- private DictBuffer mFrequencyBuffer;
- private DictBuffer mTerminalAddressTableBuffer;
- private DictBuffer mBigramBuffer;
- private DictBuffer mShortcutBuffer;
- private SparseTable mBigramAddressTable;
- private SparseTable mShortcutAddressTable;
+ protected DictBuffer mFrequencyBuffer;
+ protected DictBuffer mTerminalAddressTableBuffer;
+ private BigramContentReader mBigramReader;
+ private ShortcutContentReader mShortcutReader;
+
+ /**
+ * Raw PtNode info straight out of a trie file in version 4 dictionary.
+ */
+ protected static final class Ver4PtNodeInfo {
+ public final int mFlags;
+ public final int[] mCharacters;
+ public final int mTerminalId;
+ public final int mChildrenPos;
+ public final int mParentPos;
+ public final int mNodeSize;
+ public int mStartIndexOfCharacters;
+ public int mEndIndexOfCharacters; // exclusive
+
+ public Ver4PtNodeInfo(final int flags, final int[] characters, final int terminalId,
+ final int childrenPos, final int parentPos, final int nodeSize) {
+ mFlags = flags;
+ mCharacters = characters;
+ mTerminalId = terminalId;
+ mChildrenPos = childrenPos;
+ mParentPos = parentPos;
+ mNodeSize = nodeSize;
+ mStartIndexOfCharacters = 0;
+ mEndIndexOfCharacters = characters.length;
+ }
+ }
@UsedForTesting
/* package */ Ver4DictDecoder(final File dictDirectory, final int factoryFlag) {
@@ -79,7 +103,7 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
mDictBuffer = mFrequencyBuffer = null;
}
- private File getFile(final int fileType) {
+ protected File getFile(final int fileType) {
if (fileType == FILETYPE_TRIE) {
return new File(mDictDirectory,
mDictDirectory.getName() + FormatSpec.TRIE_FILE_EXTENSION);
@@ -108,10 +132,12 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
mFrequencyBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_FREQUENCY));
mTerminalAddressTableBuffer = mBufferFactory.getDictionaryBuffer(
getFile(FILETYPE_TERMINAL_ADDRESS_TABLE));
- mBigramBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_BIGRAM_FREQ));
- loadBigramAddressSparseTable();
- mShortcutBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_SHORTCUT));
- loadShortcutAddressSparseTable();
+ mBigramReader = new BigramContentReader(mDictDirectory.getName(),
+ mDictDirectory, mBufferFactory, false);
+ mBigramReader.openBuffers();
+ mShortcutReader = new ShortcutContentReader(mDictDirectory.getName(), mDictDirectory,
+ mBufferFactory);
+ mShortcutReader.openBuffers();
}
@Override
@@ -119,6 +145,7 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
return mDictBuffer != null;
}
+ @UsedForTesting
/* package */ DictBuffer getDictBuffer() {
return mDictBuffer;
}
@@ -136,25 +163,113 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
return header;
}
- private void loadBigramAddressSparseTable() throws IOException {
- final File lookupIndexFile = new File(mDictDirectory, mDictDirectory.getName()
- + FormatSpec.BIGRAM_FILE_EXTENSION + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX);
- final File freqsFile = new File(mDictDirectory, mDictDirectory.getName()
- + FormatSpec.BIGRAM_FILE_EXTENSION + FormatSpec.CONTENT_TABLE_FILE_SUFFIX
- + FormatSpec.BIGRAM_FREQ_CONTENT_ID);
- mBigramAddressTable = SparseTable.readFromFiles(lookupIndexFile, new File[] { freqsFile },
- FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE);
+ /**
+ * An auxiliary class for reading bigrams.
+ */
+ protected static class BigramContentReader extends SparseTableContentReader {
+ private final boolean mHasTimestamp;
+
+ public BigramContentReader(final String name, final File baseDir,
+ final DictionaryBufferFactory factory, final boolean hasTimestamp) {
+ super(name + FormatSpec.BIGRAM_FILE_EXTENSION,
+ FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
+ getContentFilenames(name, hasTimestamp), getContentIds(hasTimestamp), factory);
+ mHasTimestamp = hasTimestamp;
+ }
+
+ // TODO: Consolidate this method and BigramContentWriter.getContentFilenames.
+ protected static String[] getContentFilenames(final String name,
+ final boolean hasTimestamp) {
+ final String[] contentFilenames;
+ if (hasTimestamp) {
+ contentFilenames = new String[] { name + FormatSpec.BIGRAM_FILE_EXTENSION,
+ name + FormatSpec.BIGRAM_FILE_EXTENSION };
+ } else {
+ contentFilenames = new String[] { name + FormatSpec.BIGRAM_FILE_EXTENSION };
+ }
+ return contentFilenames;
+ }
+
+ // TODO: Consolidate this method and BigramContentWriter.getContentIds.
+ protected static String[] getContentIds(final boolean hasTimestamp) {
+ final String[] contentIds;
+ if (hasTimestamp) {
+ contentIds = new String[] { FormatSpec.BIGRAM_FREQ_CONTENT_ID,
+ FormatSpec.BIGRAM_TIMESTAMP_CONTENT_ID };
+ } else {
+ contentIds = new String[] { FormatSpec.BIGRAM_FREQ_CONTENT_ID };
+ }
+ return contentIds;
+ }
+
+ public ArrayList<PendingAttribute> readTargetsAndFrequencies(final int terminalId,
+ final DictBuffer terminalAddressTableBuffer) {
+ final ArrayList<PendingAttribute> bigrams = CollectionUtils.newArrayList();
+ read(FormatSpec.BIGRAM_FREQ_CONTENT_INDEX, terminalId,
+ new SparseTableContentReaderInterface() {
+ @Override
+ public void read(final DictBuffer buffer) {
+ while (bigrams.size() < FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
+ // If bigrams.size() reaches FormatSpec.MAX_BIGRAMS_IN_A_PTNODE,
+ // remaining bigram entries are ignored.
+ final int bigramFlags = buffer.readUnsignedByte();
+ final int targetTerminalId = buffer.readUnsignedInt24();
+ terminalAddressTableBuffer.position(targetTerminalId
+ * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE);
+ final int targetAddress =
+ terminalAddressTableBuffer.readUnsignedInt24();
+ bigrams.add(new PendingAttribute(bigramFlags
+ & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY,
+ targetAddress));
+ if (0 == (bigramFlags
+ & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) {
+ break;
+ }
+ }
+ if (bigrams.size() >= FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
+ throw new RuntimeException("Too many bigrams in a PtNode ("
+ + bigrams.size() + " but max is "
+ + FormatSpec.MAX_BIGRAMS_IN_A_PTNODE + ")");
+ }
+ }
+ });
+ if (bigrams.isEmpty()) return null;
+ return bigrams;
+ }
}
- // TODO: Let's have something like SparseTableContentsReader in this class.
- private void loadShortcutAddressSparseTable() throws IOException {
- final File lookupIndexFile = new File(mDictDirectory, mDictDirectory.getName()
- + FormatSpec.SHORTCUT_FILE_EXTENSION + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX);
- final File contentFile = new File(mDictDirectory, mDictDirectory.getName()
- + FormatSpec.SHORTCUT_FILE_EXTENSION + FormatSpec.CONTENT_TABLE_FILE_SUFFIX
- + FormatSpec.SHORTCUT_CONTENT_ID);
- mShortcutAddressTable = SparseTable.readFromFiles(lookupIndexFile,
- new File[] { contentFile }, FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE);
+ /**
+ * An auxiliary class for reading shortcuts.
+ */
+ protected static class ShortcutContentReader extends SparseTableContentReader {
+ public ShortcutContentReader(final String name, final File baseDir,
+ final DictionaryBufferFactory factory) {
+ super(name + FormatSpec.SHORTCUT_FILE_EXTENSION,
+ FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
+ new String[] { name + FormatSpec.SHORTCUT_FILE_EXTENSION },
+ new String[] { FormatSpec.SHORTCUT_CONTENT_ID }, factory);
+ }
+
+ public ArrayList<WeightedString> readShortcuts(final int terminalId) {
+ final ArrayList<WeightedString> shortcuts = CollectionUtils.newArrayList();
+ read(FormatSpec.SHORTCUT_CONTENT_INDEX, terminalId,
+ new SparseTableContentReaderInterface() {
+ @Override
+ public void read(final DictBuffer buffer) {
+ while (true) {
+ final int flags = buffer.readUnsignedByte();
+ final String word = CharEncoding.readString(buffer);
+ shortcuts.add(new WeightedString(word,
+ flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY));
+ if (0 == (flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) {
+ break;
+ }
+ }
+ }
+ });
+ if (shortcuts.isEmpty()) return null;
+ return shortcuts;
+ }
}
protected static class PtNodeReader extends AbstractDictDecoder.PtNodeReader {
@@ -168,102 +283,82 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
}
}
- private ArrayList<WeightedString> readShortcuts(final int terminalId) {
- if (mShortcutAddressTable.get(0, terminalId) == SparseTable.NOT_EXIST) return null;
-
- final ArrayList<WeightedString> ret = CollectionUtils.newArrayList();
- final int posOfShortcuts = mShortcutAddressTable.get(FormatSpec.SHORTCUT_CONTENT_INDEX,
- terminalId);
- mShortcutBuffer.position(posOfShortcuts);
- while (true) {
- final int flags = mShortcutBuffer.readUnsignedByte();
- final String word = CharEncoding.readString(mShortcutBuffer);
- ret.add(new WeightedString(word,
- flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY));
- if (0 == (flags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break;
- }
- return ret;
- }
+ private final int[] mCharacterBufferForReadingVer4PtNodeInfo
+ = new int[FormatSpec.MAX_WORD_LENGTH];
+ /**
+ * Reads PtNode from ptNodePos in the trie file and returns Ver4PtNodeInfo.
+ *
+ * @param ptNodePos the position of PtNode.
+ * @param options the format options.
+ * @return Ver4PtNodeInfo.
+ */
// TODO: Make this buffer thread safe.
// TODO: Support words longer than FormatSpec.MAX_WORD_LENGTH.
- private final int[] mCharacterBuffer = new int[FormatSpec.MAX_WORD_LENGTH];
- @Override
- public PtNodeInfo readPtNode(int ptNodePos, FormatOptions options) {
- int addressPointer = ptNodePos;
+ protected Ver4PtNodeInfo readVer4PtNodeInfo(final int ptNodePos, final FormatOptions options) {
+ int readingPos = ptNodePos;
final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer);
- addressPointer += FormatSpec.PTNODE_FLAGS_SIZE;
+ readingPos += FormatSpec.PTNODE_FLAGS_SIZE;
- final int parentAddress = PtNodeReader.readParentAddress(mDictBuffer, options);
+ final int parentPos = PtNodeReader.readParentAddress(mDictBuffer, options);
if (BinaryDictIOUtils.supportsDynamicUpdate(options)) {
- addressPointer += FormatSpec.PARENT_ADDRESS_SIZE;
+ readingPos += FormatSpec.PARENT_ADDRESS_SIZE;
}
final int characters[];
if (0 != (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS)) {
int index = 0;
int character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
+ readingPos += CharEncoding.getCharSize(character);
while (FormatSpec.INVALID_CHARACTER != character
&& index < FormatSpec.MAX_WORD_LENGTH) {
- mCharacterBuffer[index++] = character;
+ mCharacterBufferForReadingVer4PtNodeInfo[index++] = character;
character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
+ readingPos += CharEncoding.getCharSize(character);
}
- characters = Arrays.copyOfRange(mCharacterBuffer, 0, index);
+ characters = Arrays.copyOfRange(mCharacterBufferForReadingVer4PtNodeInfo, 0, index);
} else {
final int character = CharEncoding.readChar(mDictBuffer);
- addressPointer += CharEncoding.getCharSize(character);
+ readingPos += CharEncoding.getCharSize(character);
characters = new int[] { character };
}
final int terminalId;
if (0 != (FormatSpec.FLAG_IS_TERMINAL & flags)) {
terminalId = PtNodeReader.readTerminalId(mDictBuffer);
- addressPointer += FormatSpec.PTNODE_TERMINAL_ID_SIZE;
+ readingPos += FormatSpec.PTNODE_TERMINAL_ID_SIZE;
} else {
terminalId = PtNode.NOT_A_TERMINAL;
}
+ int childrenPos = PtNodeReader.readChildrenAddress(mDictBuffer, flags, options);
+ if (childrenPos != FormatSpec.NO_CHILDREN_ADDRESS) {
+ childrenPos += readingPos;
+ }
+ readingPos += BinaryDictIOUtils.getChildrenAddressSize(flags, options);
+
+ return new Ver4PtNodeInfo(flags, characters, terminalId, childrenPos, parentPos,
+ readingPos - ptNodePos);
+ }
+
+ @Override
+ public PtNodeInfo readPtNode(int ptNodePos, FormatOptions options) {
+ final Ver4PtNodeInfo nodeInfo = readVer4PtNodeInfo(ptNodePos, options);
+
final int frequency;
- if (0 != (FormatSpec.FLAG_IS_TERMINAL & flags)) {
- frequency = PtNodeReader.readFrequency(mFrequencyBuffer, terminalId);
+ if (0 != (FormatSpec.FLAG_IS_TERMINAL & nodeInfo.mFlags)) {
+ frequency = PtNodeReader.readFrequency(mFrequencyBuffer, nodeInfo.mTerminalId);
} else {
frequency = PtNode.NOT_A_TERMINAL;
}
- int childrenAddress = PtNodeReader.readChildrenAddress(mDictBuffer, flags, options);
- if (childrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) {
- childrenAddress += addressPointer;
- }
- addressPointer += BinaryDictIOUtils.getChildrenAddressSize(flags, options);
- final ArrayList<WeightedString> shortcutTargets = readShortcuts(terminalId);
-
- final ArrayList<PendingAttribute> bigrams;
- if (0 != (flags & FormatSpec.FLAG_HAS_BIGRAMS)) {
- bigrams = new ArrayList<PendingAttribute>();
- final int posOfBigrams = mBigramAddressTable.get(0 /* contentTableIndex */, terminalId);
- mBigramBuffer.position(posOfBigrams);
- while (bigrams.size() < FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
- // If bigrams.size() reaches FormatSpec.MAX_BIGRAMS_IN_A_PTNODE,
- // remaining bigram entries are ignored.
- final int bigramFlags = mBigramBuffer.readUnsignedByte();
- final int targetTerminalId = mBigramBuffer.readUnsignedInt24();
- mTerminalAddressTableBuffer.position(
- targetTerminalId * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE);
- final int targetAddress = mTerminalAddressTableBuffer.readUnsignedInt24();
- bigrams.add(new PendingAttribute(
- bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY,
- targetAddress));
- if (0 == (bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break;
- }
- if (bigrams.size() >= FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
- throw new RuntimeException("Too many bigrams in a PtNode (" + bigrams.size()
- + " but max is " + FormatSpec.MAX_BIGRAMS_IN_A_PTNODE + ")");
- }
- } else {
- bigrams = null;
- }
- return new PtNodeInfo(ptNodePos, addressPointer, flags, characters, frequency,
- parentAddress, childrenAddress, shortcutTargets, bigrams);
+
+ final ArrayList<WeightedString> shortcutTargets = mShortcutReader.readShortcuts(
+ nodeInfo.mTerminalId);
+ final ArrayList<PendingAttribute> bigrams = mBigramReader.readTargetsAndFrequencies(
+ nodeInfo.mTerminalId, mTerminalAddressTableBuffer);
+
+ return new PtNodeInfo(ptNodePos, ptNodePos + nodeInfo.mNodeSize, nodeInfo.mFlags,
+ nodeInfo.mCharacters, frequency, nodeInfo.mParentPos, nodeInfo.mChildrenPos,
+ shortcutTargets, bigrams);
}
private void deleteDictFiles() {
@@ -314,10 +409,14 @@ public class Ver4DictDecoder extends AbstractDictDecoder {
@Override
public boolean readAndFollowForwardLink() {
- final int nextAddress = mDictBuffer.readUnsignedInt24();
- if (nextAddress >= 0 && nextAddress < mDictBuffer.limit()) {
- mDictBuffer.position(nextAddress);
- return true;
+ final int forwardLinkPos = mDictBuffer.position();
+ int nextRelativePos = BinaryDictDecoderUtils.readSInt24(mDictBuffer);
+ if (nextRelativePos != FormatSpec.NO_FORWARD_LINK_ADDRESS) {
+ final int nextPos = forwardLinkPos + nextRelativePos;
+ if (nextPos >= 0 && nextPos < mDictBuffer.limit()) {
+ mDictBuffer.position(nextPos);
+ return true;
+ }
}
return false;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
index f9dcacf77..4b3acdc8e 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
@@ -25,6 +25,7 @@ import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+import com.android.inputmethod.latin.utils.CollectionUtils;
import java.io.File;
import java.io.FileNotFoundException;
@@ -32,6 +33,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
/**
@@ -45,6 +48,7 @@ public class Ver4DictEncoder implements DictEncoder {
private int mHeaderSize;
private OutputStream mTrieOutStream;
private OutputStream mFreqOutStream;
+ private OutputStream mUnigramTimestampOutStream;
private OutputStream mTerminalAddressTableOutStream;
private File mDictDir;
private String mBaseFilename;
@@ -56,73 +60,41 @@ public class Ver4DictEncoder implements DictEncoder {
mDictPlacedDir = dictPlacedDir;
}
- private interface SparseTableContentWriterInterface {
- public void write(final OutputStream outStream) throws IOException;
- }
+ private static class BigramContentWriter extends SparseTableContentWriter {
+ private final boolean mWriteTimestamp;
- private static class SparseTableContentWriter {
- private final int mContentCount;
- private final SparseTable mSparseTable;
- private final File mLookupTableFile;
- protected final File mBaseDir;
- private final File[] mAddressTableFiles;
- private final File[] mContentFiles;
- protected final OutputStream[] mContentOutStreams;
-
- public SparseTableContentWriter(final String name, final int contentCount,
- final int initialCapacity, final int blockSize, final File baseDir,
- final String[] contentFilenames, final String[] contentIds) {
- if (contentFilenames.length != contentIds.length) {
- throw new RuntimeException("The length of contentFilenames and the length of"
- + " contentIds are different " + contentFilenames.length + ", "
- + contentIds.length);
- }
- mContentCount = contentCount;
- mSparseTable = new SparseTable(initialCapacity, blockSize, contentCount);
- mLookupTableFile = new File(baseDir, name + FormatSpec.LOOKUP_TABLE_FILE_SUFFIX);
- mAddressTableFiles = new File[mContentCount];
- mContentFiles = new File[mContentCount];
- mBaseDir = baseDir;
- for (int i = 0; i < mContentCount; ++i) {
- mAddressTableFiles[i] = new File(mBaseDir,
- name + FormatSpec.CONTENT_TABLE_FILE_SUFFIX + contentIds[i]);
- mContentFiles[i] = new File(mBaseDir, contentFilenames[i] + contentIds[i]);
- }
- mContentOutStreams = new OutputStream[mContentCount];
+ public BigramContentWriter(final String name, final int initialCapacity,
+ final File baseDir, final boolean writeTimestamp) {
+ super(name + FormatSpec.BIGRAM_FILE_EXTENSION, initialCapacity,
+ FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
+ getContentFilenames(name, writeTimestamp), getContentIds(writeTimestamp));
+ mWriteTimestamp = writeTimestamp;
}
- public void openStreams() throws FileNotFoundException {
- for (int i = 0; i < mContentCount; ++i) {
- mContentOutStreams[i] = new FileOutputStream(mContentFiles[i]);
+ private static String[] getContentFilenames(final String name,
+ final boolean writeTimestamp) {
+ final String[] contentFilenames;
+ if (writeTimestamp) {
+ contentFilenames = new String[] { name + FormatSpec.BIGRAM_FILE_EXTENSION,
+ name + FormatSpec.BIGRAM_FILE_EXTENSION };
+ } else {
+ contentFilenames = new String[] { name + FormatSpec.BIGRAM_FILE_EXTENSION };
}
+ return contentFilenames;
}
- protected void write(final int contentIndex, final int index,
- final SparseTableContentWriterInterface writer) throws IOException {
- mSparseTable.set(contentIndex, index, (int) mContentFiles[contentIndex].length());
- writer.write(mContentOutStreams[contentIndex]);
- mContentOutStreams[contentIndex].flush();
- }
-
- public void closeStreams() throws IOException {
- mSparseTable.writeToFiles(mLookupTableFile, mAddressTableFiles);
- for (int i = 0; i < mContentCount; ++i) {
- mContentOutStreams[i].close();
+ private static String[] getContentIds(final boolean writeTimestamp) {
+ final String[] contentIds;
+ if (writeTimestamp) {
+ contentIds = new String[] { FormatSpec.BIGRAM_FREQ_CONTENT_ID,
+ FormatSpec.BIGRAM_TIMESTAMP_CONTENT_ID };
+ } else {
+ contentIds = new String[] { FormatSpec.BIGRAM_FREQ_CONTENT_ID };
}
- }
- }
-
- private static class BigramContentWriter extends SparseTableContentWriter {
-
- public BigramContentWriter(final String name, final int initialCapacity,
- final File baseDir) {
- super(name + FormatSpec.BIGRAM_FILE_EXTENSION, FormatSpec.BIGRAM_CONTENT_COUNT,
- initialCapacity, FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
- new String[] { name + FormatSpec.BIGRAM_FILE_EXTENSION },
- new String[] { FormatSpec.BIGRAM_FREQ_CONTENT_ID });
+ return contentIds;
}
- public void writeBigramsForOneWord(final int terminalId,
+ public void writeBigramsForOneWord(final int terminalId, final int bigramCount,
final Iterator<WeightedString> bigramIterator, final FusionDictionary dict)
throws IOException {
write(FormatSpec.BIGRAM_FREQ_CONTENT_INDEX, terminalId,
@@ -130,8 +102,16 @@ public class Ver4DictEncoder implements DictEncoder {
@Override
public void write(final OutputStream outStream) throws IOException {
writeBigramsForOneWordInternal(outStream, bigramIterator, dict);
- }
- });
+ }});
+ if (mWriteTimestamp) {
+ write(FormatSpec.BIGRAM_TIMESTAMP_CONTENT_INDEX, terminalId,
+ new SparseTableContentWriterInterface() {
+ @Override
+ public void write(final OutputStream outStream) throws IOException {
+ initBigramTimestampsCountersAndLevelsForOneWordInternal(outStream,
+ bigramCount);
+ }});
+ }
}
private void writeBigramsForOneWordInternal(final OutputStream outStream,
@@ -151,13 +131,26 @@ public class Ver4DictEncoder implements DictEncoder {
FormatSpec.PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE);
}
}
+
+ private void initBigramTimestampsCountersAndLevelsForOneWordInternal(
+ final OutputStream outStream, final int bigramCount) throws IOException {
+ for (int i = 0; i < bigramCount; ++i) {
+ // TODO: Figure out what initial values should be.
+ BinaryDictEncoderUtils.writeUIntToStream(outStream, 0 /* value */,
+ FormatSpec.BIGRAM_TIMESTAMP_SIZE);
+ BinaryDictEncoderUtils.writeUIntToStream(outStream, 0 /* value */,
+ FormatSpec.BIGRAM_COUNTER_SIZE);
+ BinaryDictEncoderUtils.writeUIntToStream(outStream, 0 /* value */,
+ FormatSpec.BIGRAM_LEVEL_SIZE);
+ }
+ }
}
private static class ShortcutContentWriter extends SparseTableContentWriter {
public ShortcutContentWriter(final String name, final int initialCapacity,
final File baseDir) {
- super(name + FormatSpec.SHORTCUT_FILE_EXTENSION, FormatSpec.SHORTCUT_CONTENT_COUNT,
- initialCapacity, FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
+ super(name + FormatSpec.SHORTCUT_FILE_EXTENSION, initialCapacity,
+ FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
new String[] { name + FormatSpec.SHORTCUT_FILE_EXTENSION },
new String[] { FormatSpec.SHORTCUT_CONTENT_ID });
}
@@ -193,18 +186,20 @@ public class Ver4DictEncoder implements DictEncoder {
mDictDir = new File(mDictPlacedDir, mBaseFilename);
final File trieFile = new File(mDictDir, mBaseFilename + FormatSpec.TRIE_FILE_EXTENSION);
final File freqFile = new File(mDictDir, mBaseFilename + FormatSpec.FREQ_FILE_EXTENSION);
+ final File timestampFile = new File(mDictDir,
+ mBaseFilename + FormatSpec.UNIGRAM_TIMESTAMP_FILE_EXTENSION);
final File terminalAddressTableFile = new File(mDictDir,
mBaseFilename + FormatSpec.TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
if (!mDictDir.isDirectory()) {
if (mDictDir.exists()) mDictDir.delete();
mDictDir.mkdirs();
}
- if (!trieFile.exists()) trieFile.createNewFile();
- if (!freqFile.exists()) freqFile.createNewFile();
- if (!terminalAddressTableFile.exists()) terminalAddressTableFile.createNewFile();
mTrieOutStream = new FileOutputStream(trieFile);
mFreqOutStream = new FileOutputStream(freqFile);
mTerminalAddressTableOutStream = new FileOutputStream(terminalAddressTableFile);
+ if (formatOptions.mHasTimestamp) {
+ mUnigramTimestampOutStream = new FileOutputStream(timestampFile);
+ }
}
private void close() throws IOException {
@@ -218,6 +213,9 @@ public class Ver4DictEncoder implements DictEncoder {
if (mTerminalAddressTableOutStream != null) {
mTerminalAddressTableOutStream.close();
}
+ if (mUnigramTimestampOutStream != null) {
+ mUnigramTimestampOutStream.close();
+ }
} finally {
mTrieOutStream = null;
mFreqOutStream = null;
@@ -246,10 +244,29 @@ public class Ver4DictEncoder implements DictEncoder {
MakedictLog.i("Flattening the tree...");
ArrayList<PtNodeArray> flatNodes = BinaryDictEncoderUtils.flattenTree(dict.mRootNodeArray);
int terminalCount = 0;
+ final ArrayList<PtNode> nodes = CollectionUtils.newArrayList();
for (final PtNodeArray array : flatNodes) {
for (final PtNode node : array.mData) {
- if (node.isTerminal()) node.mTerminalId = terminalCount++;
+ if (node.isTerminal()) {
+ nodes.add(node);
+ node.mTerminalId = terminalCount++;
+ }
+ }
+ }
+ Collections.sort(nodes, new Comparator<PtNode>() {
+ @Override
+ public int compare(final PtNode lhs, final PtNode rhs) {
+ if (lhs.mFrequency != rhs.mFrequency) {
+ return lhs.mFrequency < rhs.mFrequency ? -1 : 1;
+ }
+ if (lhs.mTerminalId < rhs.mTerminalId) return -1;
+ if (lhs.mTerminalId > rhs.mTerminalId) return 1;
+ return 0;
}
+ });
+ int count = 0;
+ for (final PtNode node : nodes) {
+ node.mTerminalId = count++;
}
MakedictLog.i("Computing addresses...");
@@ -257,7 +274,11 @@ public class Ver4DictEncoder implements DictEncoder {
if (MakedictLog.DBG) BinaryDictEncoderUtils.checkFlatPtNodeArrayList(flatNodes);
writeTerminalData(flatNodes, terminalCount);
- mBigramWriter = new BigramContentWriter(mBaseFilename, terminalCount, mDictDir);
+ if (formatOptions.mHasTimestamp) {
+ initUnigramTimestamps(terminalCount);
+ }
+ mBigramWriter = new BigramContentWriter(mBaseFilename, terminalCount, mDictDir,
+ formatOptions.mHasTimestamp);
writeBigrams(flatNodes, dict);
mShortcutWriter = new ShortcutContentWriter(mBaseFilename, terminalCount, mDictDir);
writeShortcuts(flatNodes);
@@ -348,7 +369,7 @@ public class Ver4DictEncoder implements DictEncoder {
for (final PtNodeArray nodeArray : flatNodes) {
for (final PtNode ptNode : nodeArray.mData) {
if (ptNode.mBigrams != null) {
- mBigramWriter.writeBigramsForOneWord(ptNode.mTerminalId,
+ mBigramWriter.writeBigramsForOneWord(ptNode.mTerminalId, ptNode.mBigrams.size(),
ptNode.mBigrams.iterator(), dict);
}
}
@@ -408,4 +429,11 @@ public class Ver4DictEncoder implements DictEncoder {
mFreqOutStream.write(freqBuf);
mTerminalAddressTableOutStream.write(terminalAddressTableBuf);
}
+
+ private void initUnigramTimestamps(final int terminalCount) throws IOException {
+ // Initial value of time stamps for each word is 0.
+ final byte[] unigramTimestampBuf =
+ new byte[terminalCount * FormatSpec.UNIGRAM_TIMESTAMP_SIZE];
+ mUnigramTimestampOutStream.write(unigramTimestampBuf);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java
index 3d8f186ba..65860ee72 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictUpdater.java
@@ -17,23 +17,124 @@
package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
+import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
+import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
+import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+import android.util.Log;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
/**
* An implementation of DictUpdater for version 4 binary dictionary.
*/
@UsedForTesting
public class Ver4DictUpdater extends Ver4DictDecoder implements DictUpdater {
+ private static final String TAG = Ver4DictUpdater.class.getSimpleName();
+
+ private OutputStream mDictStream;
+ private final File mFrequencyFile;
@UsedForTesting
public Ver4DictUpdater(final File dictDirectory, final int factoryType) {
// DictUpdater must have an updatable DictBuffer.
super(dictDirectory, ((factoryType & MASK_DICTBUFFER) == USE_BYTEARRAY)
? USE_BYTEARRAY : USE_WRITABLE_BYTEBUFFER);
+ mFrequencyFile = getFile(FILETYPE_FREQUENCY);
+ }
+
+ private static class BigramContentUpdater extends SparseTableContentUpdater {
+ private final boolean mHasTimestamp;
+
+ public BigramContentUpdater(final String name, final File baseDir,
+ final boolean hasTimestamp) {
+ super(name + FormatSpec.BIGRAM_FILE_EXTENSION,
+ FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
+ BigramContentReader.getContentFilenames(name, hasTimestamp),
+ BigramContentReader.getContentIds(hasTimestamp),
+ new DictionaryBufferFromWritableByteBufferFactory());
+ mHasTimestamp = hasTimestamp;
+ }
+
+ public void insertBigramEntries(final int terminalId, final int frequency,
+ final ArrayList<PendingAttribute> entries) throws IOException {
+ if (terminalId < 0) {
+ throw new RuntimeException("Invalid terminal id : " + terminalId);
+ }
+ openStreamsAndBuffers();
+
+ if (entries == null || entries.isEmpty()) {
+ setContentValue(FormatSpec.BIGRAM_FREQ_CONTENT_INDEX, terminalId,
+ SparseTable.NOT_EXIST);
+ return;
+ }
+ final int positionOfEntries =
+ (int) mContentFiles[FormatSpec.BIGRAM_FREQ_CONTENT_INDEX].length();
+ setContentValue(FormatSpec.BIGRAM_FREQ_CONTENT_INDEX, terminalId, positionOfEntries);
+
+ final Iterator<PendingAttribute> bigramIterator = entries.iterator();
+ while (bigramIterator.hasNext()) {
+ final PendingAttribute entry = bigramIterator.next();
+ final int flags = BinaryDictEncoderUtils.makeBigramFlags(bigramIterator.hasNext(),
+ 0 /* offset */, entry.mFrequency, frequency, "" /* word */);
+ BinaryDictEncoderUtils.writeUIntToStream(
+ mContentOutStreams[FormatSpec.BIGRAM_FREQ_CONTENT_INDEX], flags,
+ FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
+ BinaryDictEncoderUtils.writeUIntToStream(
+ mContentOutStreams[FormatSpec.BIGRAM_FREQ_CONTENT_INDEX], entry.mAddress,
+ FormatSpec.PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE);
+ }
+ close();
+ }
+ }
+
+ private static class ShortcutContentUpdater extends SparseTableContentUpdater {
+ public ShortcutContentUpdater(final String name, final File baseDir) {
+ super(name + FormatSpec.SHORTCUT_FILE_EXTENSION,
+ FormatSpec.SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, baseDir,
+ new String[] { name + FormatSpec.SHORTCUT_FILE_EXTENSION },
+ new String[] { FormatSpec.SHORTCUT_CONTENT_ID },
+ new DictionaryBufferFromWritableByteBufferFactory());
+ }
+
+ public void insertShortcuts(final int terminalId,
+ final ArrayList<WeightedString> shortcuts) throws IOException {
+ if (terminalId < 0) {
+ throw new RuntimeException("Invalid terminal id : " + terminalId);
+ }
+ openStreamsAndBuffers();
+ if (shortcuts == null || shortcuts.isEmpty()) {
+ setContentValue(FormatSpec.SHORTCUT_CONTENT_INDEX, terminalId,
+ SparseTable.NOT_EXIST);
+ return;
+ }
+
+ final int positionOfShortcuts =
+ (int) mContentFiles[FormatSpec.SHORTCUT_CONTENT_INDEX].length();
+ setContentValue(FormatSpec.SHORTCUT_CONTENT_INDEX, terminalId, positionOfShortcuts);
+
+ final Iterator<WeightedString> shortcutIterator = shortcuts.iterator();
+ while (shortcutIterator.hasNext()) {
+ final WeightedString target = shortcutIterator.next();
+ final int shortcutFlags = BinaryDictEncoderUtils.makeShortcutFlags(
+ shortcutIterator.hasNext(), target.mFrequency);
+ BinaryDictEncoderUtils.writeUIntToStream(
+ mContentOutStreams[FormatSpec.SHORTCUT_CONTENT_INDEX], shortcutFlags,
+ FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
+ CharEncoding.writeString(mContentOutStreams[FormatSpec.SHORTCUT_CONTENT_INDEX],
+ target.mWord);
+ }
+ close();
+ }
}
@Override
@@ -49,11 +150,622 @@ public class Ver4DictUpdater extends Ver4DictDecoder implements DictUpdater {
}
}
- @Override
+ private int getNewTerminalId() {
+ // The size of frequency file is FormatSpec.FREQUENCY_AND_FLAGS_SIZE * number of terminals
+ // because each terminal always has a frequency.
+ // So we can get a fresh terminal id by this logic.
+ // CAVEAT: we are reading the file size from the disk each time: beware of race conditions,
+ // even on one thread.
+ return (int) (mFrequencyFile.length() / FormatSpec.FREQUENCY_AND_FLAGS_SIZE);
+ }
+
+ private void updateParentPosIfNotMoved(final int nodePos, final int newParentPos,
+ final FormatOptions formatOptions) {
+ final int originalPos = getPosition();
+ setPosition(nodePos);
+ final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer);
+ if (!BinaryDictIOUtils.isMovedPtNode(flags, formatOptions)) {
+ final int parentOffset = newParentPos - nodePos;
+ BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, parentOffset);
+ }
+ setPosition(originalPos);
+ }
+
+ private void updateParentPositions(final int nodeArrayPos, final int newParentPos,
+ final FormatOptions formatOptions) {
+ final int originalPos = mDictBuffer.position();
+ mDictBuffer.position(nodeArrayPos);
+ int jumpCount = 0;
+ do {
+ final int count = readPtNodeCount();
+ for (int i = 0; i < count; ++i) {
+ updateParentPosIfNotMoved(getPosition(), newParentPos, formatOptions);
+ skipPtNode(formatOptions);
+ }
+ if (!readAndFollowForwardLink()) break;
+ } while (jumpCount++ < DynamicBinaryDictIOUtils.MAX_JUMPS);
+ setPosition(originalPos);
+ }
+
+ private void updateChildrenPos(final int nodePos, final int newChildrenPos,
+ final FormatOptions options) {
+ final int originalPos = getPosition();
+ setPosition(nodePos);
+ final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer);
+ PtNodeReader.readParentAddress(mDictBuffer, options);
+ BinaryDictIOUtils.skipString(mDictBuffer,
+ (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0);
+ if ((flags & FormatSpec.FLAG_IS_TERMINAL) != 0) PtNodeReader.readTerminalId(mDictBuffer);
+ final int basePos = getPosition();
+ BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, newChildrenPos - basePos);
+ setPosition(originalPos);
+ }
+
+ private void updateTerminalPosition(final int terminalId, final int position) {
+ if (terminalId == PtNode.NOT_A_TERMINAL
+ || terminalId * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE
+ >= mTerminalAddressTableBuffer.limit()) return;
+ mTerminalAddressTableBuffer.position(terminalId
+ * FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE);
+ BinaryDictEncoderUtils.writeUIntToDictBuffer(mTerminalAddressTableBuffer, position,
+ FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE);
+ }
+
+ private void updateForwardLink(final int nodeArrayPos, final int newForwardLink,
+ final FormatOptions formatOptions) {
+ final int originalPos = getPosition();
+ setPosition(nodeArrayPos);
+ int jumpCount = 0;
+ while (jumpCount++ < DynamicBinaryDictIOUtils.MAX_JUMPS) {
+ final int ptNodeCount = readPtNodeCount();
+ for (int i = 0; i < ptNodeCount; ++i) {
+ skipPtNode(formatOptions);
+ }
+ final int forwardLinkPos = getPosition();
+ if (!readAndFollowForwardLink()) {
+ setPosition(forwardLinkPos);
+ BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, newForwardLink - forwardLinkPos);
+ break;
+ }
+ }
+ setPosition(originalPos);
+ }
+
+ private void markPtNodeAsMoved(final int nodePos, final int newNodePos,
+ final FormatOptions options) {
+ final int originalPos = getPosition();
+ updateParentPosIfNotMoved(nodePos, newNodePos, options);
+ setPosition(nodePos);
+ final int currentFlags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer);
+ setPosition(nodePos);
+ mDictBuffer.put((byte) (FormatSpec.FLAG_IS_MOVED
+ | (currentFlags & (~FormatSpec.MASK_MOVE_AND_DELETE_FLAG))));
+ final int offset = newNodePos - nodePos;
+ BinaryDictIOUtils.writeSInt24ToBuffer(mDictBuffer, offset);
+ setPosition(originalPos);
+ }
+
+ /**
+ * Writes a PtNode to an output stream from a Ver4PtNodeInfo.
+ *
+ * @param nodePos the position of the head of the PtNode.
+ * @param info the PtNode info to be written.
+ * @return the size written, in bytes.
+ */
+ private int writePtNode(final int nodePos, final Ver4PtNodeInfo info) throws IOException {
+ int written = 0;
+
+ // Write flags.
+ mDictStream.write((byte) (info.mFlags & 0xFF));
+ written += FormatSpec.PTNODE_FLAGS_SIZE;
+
+ // Write the parent position.
+ final int parentOffset = info.mParentPos == FormatSpec.NO_PARENT_ADDRESS ?
+ FormatSpec.NO_PARENT_ADDRESS : info.mParentPos - nodePos;
+ BinaryDictIOUtils.writeSInt24ToStream(mDictStream, parentOffset);
+ written += FormatSpec.PARENT_ADDRESS_SIZE;
+
+ // Write a string.
+ if (((info.mFlags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0)
+ != (info.mEndIndexOfCharacters - info.mStartIndexOfCharacters > 1)) {
+ throw new RuntimeException("Inconsistent flags : hasMultipleChars = "
+ + ((info.mFlags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0) + ", length = "
+ + (info.mEndIndexOfCharacters - info.mStartIndexOfCharacters));
+ }
+ written += CharEncoding.writeCodePoints(mDictStream, info.mCharacters,
+ info.mStartIndexOfCharacters, info.mEndIndexOfCharacters);
+
+ // Write the terminal id.
+ if ((info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0) {
+ BinaryDictEncoderUtils.writeUIntToStream(mDictStream, info.mTerminalId,
+ FormatSpec.PTNODE_TERMINAL_ID_SIZE);
+ written += FormatSpec.PTNODE_TERMINAL_ID_SIZE;
+ }
+
+ // Write the children position.
+ final int childrenOffset = info.mChildrenPos == FormatSpec.NO_CHILDREN_ADDRESS
+ ? 0 : info.mChildrenPos - (nodePos + written);
+ BinaryDictIOUtils.writeSInt24ToStream(mDictStream, childrenOffset);
+ written += FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
+
+ return written;
+ }
+
+ /**
+ * Helper method to split and move PtNode.
+ *
+ * @param ptNodeArrayPos the position of PtNodeArray which contains the split and moved PtNode.
+ * @param splittedPtNodeToMovePos the position of the split and moved PtNode.
+ * @param newParent the parent PtNode after splitting.
+ * @param newChildren the children PtNodes after splitting.
+ * @param newParentStartPos where to write the new parent.
+ * @param formatOptions the format options.
+ */
+ private void writeSplittedPtNodes(final int ptNodeArrayPos, final int splittedPtNodeToMovePos,
+ final Ver4PtNodeInfo newParent, final Ver4PtNodeInfo[] newChildren,
+ final int newParentStartPos,
+ final FormatOptions formatOptions) throws IOException {
+ updateTerminalPosition(newParent.mTerminalId,
+ newParentStartPos + 1 /* size of PtNodeCount */);
+ int written = writePtNodeArray(newParentStartPos, new Ver4PtNodeInfo[] { newParent },
+ FormatSpec.NO_FORWARD_LINK_ADDRESS);
+ final int childrenStartPos = newParentStartPos + written;
+ writePtNodeArray(childrenStartPos, newChildren, FormatSpec.NO_FORWARD_LINK_ADDRESS);
+ int childrenNodePos = childrenStartPos + 1 /* size of PtNodeCount */;
+ for (final Ver4PtNodeInfo info : newChildren) {
+ updateTerminalPosition(info.mTerminalId, childrenNodePos);
+ childrenNodePos += computePtNodeSize(info.mCharacters, info.mStartIndexOfCharacters,
+ info.mEndIndexOfCharacters,
+ (info.mFlags & FormatSpec.FLAG_IS_TERMINAL) != 0);
+ }
+
+ // Mark as moved.
+ markPtNodeAsMoved(splittedPtNodeToMovePos, newParentStartPos + 1 /* size of PtNodeCount */,
+ formatOptions);
+ updateForwardLink(ptNodeArrayPos, newParentStartPos, formatOptions);
+ }
+
+ /**
+ * Writes a node array to the stream.
+ *
+ * @param nodeArrayPos the position of the head of the node array.
+ * @param infos an array of Ver4PtNodeInfo to be written.
+ * @return the written length in bytes.
+ */
+ private int writePtNodeArray(final int nodeArrayPos, final Ver4PtNodeInfo[] infos,
+ final int forwardLink) throws IOException {
+ int written = BinaryDictIOUtils.writePtNodeCount(mDictStream, infos.length);
+ for (int i = 0; i < infos.length; ++i) {
+ written += writePtNode(nodeArrayPos + written, infos[i]);
+ }
+ BinaryDictIOUtils.writeSInt24ToStream(mDictStream, forwardLink);
+ written += FormatSpec.FORWARD_LINK_ADDRESS_SIZE;
+ return written;
+ }
+
+ private int computePtNodeSize(final int[] codePoints, final int startIndex, final int endIndex,
+ final boolean isTerminal) {
+ return FormatSpec.PTNODE_FLAGS_SIZE + FormatSpec.PARENT_ADDRESS_SIZE
+ + CharEncoding.getCharArraySize(codePoints, startIndex, endIndex)
+ + (endIndex - startIndex > 1 ? FormatSpec.PTNODE_TERMINATOR_SIZE : 0)
+ + (isTerminal ? FormatSpec.PTNODE_TERMINAL_ID_SIZE : 0)
+ + FormatSpec.SIGNED_CHILDREN_ADDRESS_SIZE;
+ }
+
+ private void writeNewSinglePtNodeWithAttributes(final int[] codePoints,
+ final boolean hasShortcuts, final int terminalId, final boolean hasBigrams,
+ final boolean isNotAWord, final boolean isBlackListEntry, final int parentPos,
+ final FormatOptions formatOptions) throws IOException {
+ final int newNodeArrayPos = mDictBuffer.limit();
+ final int newNodeFlags = BinaryDictEncoderUtils.makePtNodeFlags(codePoints.length > 1,
+ terminalId != PtNode.NOT_A_TERMINAL, FormatSpec.FLAG_IS_NOT_MOVED, hasShortcuts,
+ hasBigrams, isNotAWord, isBlackListEntry, formatOptions);
+ final Ver4PtNodeInfo info = new Ver4PtNodeInfo(newNodeFlags, codePoints, terminalId,
+ FormatSpec.NO_CHILDREN_ADDRESS, parentPos, 0 /* nodeSize */);
+ writePtNodeArray(newNodeArrayPos, new Ver4PtNodeInfo[] { info },
+ FormatSpec.NO_FORWARD_LINK_ADDRESS);
+ }
+
+ private int setMultipleCharsInFlags(final int currentFlags, final boolean hasMultipleChars) {
+ final int flags;
+ if (hasMultipleChars) {
+ flags = currentFlags | FormatSpec.FLAG_HAS_MULTIPLE_CHARS;
+ } else {
+ flags = currentFlags & (~FormatSpec.FLAG_HAS_MULTIPLE_CHARS);
+ }
+ return flags;
+ }
+
+ private int setIsNotAWordInFlags(final int currentFlags, final boolean isNotAWord) {
+ final int flags;
+ if (isNotAWord) {
+ flags = currentFlags | FormatSpec.FLAG_IS_NOT_A_WORD;
+ } else {
+ flags = currentFlags & (~FormatSpec.FLAG_IS_NOT_A_WORD);
+ }
+ return flags;
+ }
+
+ private int setIsBlackListEntryInFlags(final int currentFlags, final boolean isBlackListEntry) {
+ final int flags;
+ if (isBlackListEntry) {
+ flags = currentFlags | FormatSpec.FLAG_IS_BLACKLISTED;
+ } else {
+ flags = currentFlags & (~FormatSpec.FLAG_IS_BLACKLISTED);
+ }
+ return flags;
+ }
+
+ /**
+ * Splits a PtNode.
+ *
+ * abcd - ef
+ *
+ * -> inserting "abc"
+ *
+ * abc - d - ef
+ *
+ * @param nodeArrayToSplitPos the position of PtNodeArray which contains the PtNode to split.
+ * @param nodeToSplitPos the position of the PtNode to split.
+ * @param nodeToSplitInfo the information of the PtNode to split.
+ * @param indexToSplit the index where to split in the code points array.
+ * @param parentOfNodeToSplitPos the absolute position of a parent of the node to split.
+ * @param newTerminalId the terminal id of the inserted node (corresponds to "d").
+ * @param hasShortcuts whether the inserted word should have shortcuts.
+ * @param hasBigrams whether the inserted word should have bigrams.
+ * @param isNotAWord whether the inserted word should be not a word.
+ * @param isBlackListEntry whether the inserted word should be a black list entry.
+ * @param formatOptions the format options.
+ */
+ private void splitOnly(final int nodeArrayToSplitPos, final int nodeToSplitPos,
+ final Ver4PtNodeInfo nodeToSplitInfo, final int indexToSplit,
+ final int parentOfNodeToSplitPos, final int newTerminalId, final boolean hasShortcuts,
+ final boolean hasBigrams, final boolean isNotAWord, final boolean isBlackListEntry,
+ final FormatOptions formatOptions) throws IOException {
+ final int parentNodeArrayStartPos = mDictBuffer.limit();
+ final int parentNodeStartPos = parentNodeArrayStartPos + 1 /* size of PtNodeCount */;
+ final int parentFlags = BinaryDictEncoderUtils.makePtNodeFlags(indexToSplit > 1,
+ true /* isTerminal */, FormatSpec.FLAG_IS_NOT_MOVED, hasShortcuts, hasBigrams,
+ isNotAWord, isBlackListEntry, formatOptions);
+ final Ver4PtNodeInfo parentInfo = new Ver4PtNodeInfo(parentFlags,
+ nodeToSplitInfo.mCharacters, newTerminalId, parentNodeStartPos
+ + computePtNodeSize(nodeToSplitInfo.mCharacters, 0, indexToSplit, true)
+ + FormatSpec.FORWARD_LINK_ADDRESS_SIZE,
+ parentOfNodeToSplitPos, 0 /* nodeSize */);
+ parentInfo.mStartIndexOfCharacters = 0;
+ parentInfo.mEndIndexOfCharacters = indexToSplit;
+
+ // Write the child.
+ final int childrenFlags = setMultipleCharsInFlags(nodeToSplitInfo.mFlags,
+ nodeToSplitInfo.mCharacters.length - indexToSplit > 1);
+ final Ver4PtNodeInfo childrenInfo = new Ver4PtNodeInfo(childrenFlags,
+ nodeToSplitInfo.mCharacters, nodeToSplitInfo.mTerminalId,
+ nodeToSplitInfo.mChildrenPos, parentNodeStartPos, 0 /* nodeSize */);
+ childrenInfo.mStartIndexOfCharacters = indexToSplit;
+ childrenInfo.mEndIndexOfCharacters = nodeToSplitInfo.mCharacters.length;
+ if (nodeToSplitInfo.mChildrenPos != FormatSpec.NO_CHILDREN_ADDRESS) {
+ updateParentPositions(nodeToSplitInfo.mChildrenPos,
+ parentInfo.mChildrenPos + 1 /* size of PtNodeCount */, formatOptions);
+ }
+
+ writeSplittedPtNodes(nodeArrayToSplitPos, nodeToSplitPos, parentInfo,
+ new Ver4PtNodeInfo[] { childrenInfo }, parentNodeArrayStartPos, formatOptions);
+ }
+
+ /**
+ * Split and branch a PtNode.
+ *
+ * ab - cd
+ *
+ * -> inserting "ac"
+ *
+ * a - b - cd
+ * |
+ * - c
+ *
+ * @param nodeArrayToSplitPos the position of PtNodeArray which contains the PtNode to split.
+ * @param nodeToSplitPos the position of the PtNode to split.
+ * @param nodeToSplitInfo the information of the PtNode to split.
+ * @param indexToSplit the index where to split in the code points array.
+ * @param parentOfNodeToSplitPos the absolute position of parent of the node to split.
+ * @param newWordSuffixCodePoints the suffix of the newly inserted word (corresponds to "c").
+ * @param startIndexOfNewWordSuffixCodePoints the start index in newWordSuffixCodePoints where
+ * the suffix starts.
+ * @param newTerminalId the terminal id of the inserted node (correspond to "c").
+ * @param hasShortcuts whether the inserted word should have shortcuts.
+ * @param hasBigrams whether the inserted word should have bigrams.
+ * @param isNotAWord whether the inserted word should be not a word.
+ * @param isBlackListEntry whether the inserted word should be a black list entry.
+ * @param formatOptions the format options.
+ */
+ private void splitAndBranch(final int nodeArrayToSplitPos, final int nodeToSplitPos,
+ final Ver4PtNodeInfo nodeToSplitInfo, final int indexToSplit,
+ final int parentOfNodeToSplitPos, final int[] newWordSuffixCodePoints,
+ final int startIndexOfNewWordSuffixCodePoints,
+ final int newTerminalId,
+ final boolean hasShortcuts, final boolean hasBigrams, final boolean isNotAWord,
+ final boolean isBlackListEntry, final FormatOptions formatOptions) throws IOException {
+ final int parentNodeArrayStartPos = mDictBuffer.limit();
+ final int parentNodeStartPos = parentNodeArrayStartPos + 1 /* size of PtNodeCount */;
+ final int parentFlags = BinaryDictEncoderUtils.makePtNodeFlags(
+ indexToSplit > 1,
+ false /* isTerminal */, FormatSpec.FLAG_IS_NOT_MOVED,
+ false /* hasShortcut */, false /* hasBigrams */,
+ false /* isNotAWord */, false /* isBlackListEntry */, formatOptions);
+ final Ver4PtNodeInfo parentInfo = new Ver4PtNodeInfo(parentFlags,
+ nodeToSplitInfo.mCharacters, PtNode.NOT_A_TERMINAL,
+ parentNodeStartPos
+ + computePtNodeSize(nodeToSplitInfo.mCharacters, 0, indexToSplit, false)
+ + FormatSpec.FORWARD_LINK_ADDRESS_SIZE,
+ parentOfNodeToSplitPos, 0 /* nodeSize */);
+ parentInfo.mStartIndexOfCharacters = 0;
+ parentInfo.mEndIndexOfCharacters = indexToSplit;
+
+ final int childrenNodeArrayStartPos = parentNodeStartPos
+ + computePtNodeSize(nodeToSplitInfo.mCharacters, 0, indexToSplit, false)
+ + FormatSpec.FORWARD_LINK_ADDRESS_SIZE;
+ final int firstChildrenFlags = BinaryDictEncoderUtils.makePtNodeFlags(
+ newWordSuffixCodePoints.length - startIndexOfNewWordSuffixCodePoints > 1,
+ true /* isTerminal */, FormatSpec.FLAG_IS_NOT_MOVED, hasShortcuts, hasBigrams,
+ isNotAWord, isBlackListEntry, formatOptions);
+ final Ver4PtNodeInfo firstChildrenInfo = new Ver4PtNodeInfo(firstChildrenFlags,
+ newWordSuffixCodePoints, newTerminalId,
+ FormatSpec.NO_CHILDREN_ADDRESS, parentNodeStartPos,
+ 0 /* nodeSize */);
+ firstChildrenInfo.mStartIndexOfCharacters = startIndexOfNewWordSuffixCodePoints;
+ firstChildrenInfo.mEndIndexOfCharacters = newWordSuffixCodePoints.length;
+
+ final int secondChildrenStartPos = childrenNodeArrayStartPos + 1 /* size of ptNodeCount */
+ + computePtNodeSize(newWordSuffixCodePoints, startIndexOfNewWordSuffixCodePoints,
+ newWordSuffixCodePoints.length, true /* isTerminal */);
+ final int secondChildrenFlags = setMultipleCharsInFlags(nodeToSplitInfo.mFlags,
+ nodeToSplitInfo.mCharacters.length - indexToSplit > 1);
+ final Ver4PtNodeInfo secondChildrenInfo = new Ver4PtNodeInfo(secondChildrenFlags,
+ nodeToSplitInfo.mCharacters, nodeToSplitInfo.mTerminalId,
+ nodeToSplitInfo.mChildrenPos, parentNodeStartPos, 0 /* nodeSize */);
+ secondChildrenInfo.mStartIndexOfCharacters = indexToSplit;
+ secondChildrenInfo.mEndIndexOfCharacters = nodeToSplitInfo.mCharacters.length;
+ if (nodeToSplitInfo.mChildrenPos != FormatSpec.NO_CHILDREN_ADDRESS) {
+ updateParentPositions(nodeToSplitInfo.mChildrenPos, secondChildrenStartPos,
+ formatOptions);
+ }
+
+ writeSplittedPtNodes(nodeArrayToSplitPos, nodeToSplitPos, parentInfo,
+ new Ver4PtNodeInfo[] { firstChildrenInfo, secondChildrenInfo },
+ parentNodeArrayStartPos, formatOptions);
+ }
+
+ /**
+ * Inserts a word into the trie file and returns the position of inserted terminal node.
+ * If the insertion is failed, returns FormatSpec.NOT_VALID_WORD.
+ */
+ @UsedForTesting
+ private int insertWordToTrie(final String word, final int newTerminalId,
+ final boolean isNotAWord, final boolean isBlackListEntry, final boolean hasBigrams,
+ final boolean hasShortcuts) throws IOException, UnsupportedFormatException {
+ setPosition(0);
+ final FileHeader header = readHeader();
+
+ final int[] codePoints = FusionDictionary.getCodePoints(word);
+ final int wordLen = codePoints.length;
+
+ int wordPos = 0;
+ for (int depth = 0; depth < FormatSpec.MAX_WORD_LENGTH; /* nop */) {
+ final int nodeArrayPos = getPosition();
+ final int ptNodeCount = readPtNodeCount();
+ boolean goToChildren = false;
+ int parentPos = FormatSpec.NO_PARENT_ADDRESS;
+ for (int i = 0; i < ptNodeCount; ++i) {
+ final int nodePos = getPosition();
+ final Ver4PtNodeInfo nodeInfo = readVer4PtNodeInfo(nodePos, header.mFormatOptions);
+ if (BinaryDictIOUtils.isMovedPtNode(nodeInfo.mFlags, header.mFormatOptions)) {
+ continue;
+ }
+ if (nodeInfo.mParentPos != FormatSpec.NO_PARENT_ADDRESS) {
+ parentPos = nodePos + nodeInfo.mParentPos;
+ }
+
+ final boolean firstCharacterMatched =
+ codePoints[wordPos] == nodeInfo.mCharacters[0];
+ boolean allCharactersMatched = true;
+ int firstDifferentCharacterIndex = -1;
+ for (int p = 0; p < nodeInfo.mCharacters.length; ++p) {
+ if (wordPos + p >= codePoints.length) break;
+ if (codePoints[wordPos + p] != nodeInfo.mCharacters[p]) {
+ if (firstDifferentCharacterIndex == -1) {
+ firstDifferentCharacterIndex = p;
+ }
+ allCharactersMatched = false;
+ }
+ }
+
+ if (!firstCharacterMatched) {
+ // Go to the next sibling node.
+ continue;
+ }
+
+ if (!allCharactersMatched) {
+ final int parentNodeArrayStartPos = mDictBuffer.limit();
+ splitAndBranch(nodeArrayPos, nodePos, nodeInfo, firstDifferentCharacterIndex,
+ parentPos, codePoints, wordPos + firstDifferentCharacterIndex,
+ newTerminalId, hasShortcuts, hasBigrams, isNotAWord,
+ isBlackListEntry, header.mFormatOptions);
+
+ return parentNodeArrayStartPos + computePtNodeSize(codePoints, wordPos,
+ wordPos + firstDifferentCharacterIndex, false)
+ + FormatSpec.FORWARD_LINK_ADDRESS_SIZE + 1 /* size of PtNodeCount */;
+ }
+
+ if (wordLen - wordPos < nodeInfo.mCharacters.length) {
+ final int parentNodeArrayStartPos = mDictBuffer.limit();
+ splitOnly(nodeArrayPos, nodePos, nodeInfo, wordLen - wordPos, parentPos,
+ newTerminalId, hasShortcuts, hasBigrams, isNotAWord, isBlackListEntry,
+ header.mFormatOptions);
+
+ // Return the position of the inserted word.
+ return parentNodeArrayStartPos + 1 /* size of PtNodeCount */;
+ }
+
+ wordPos += nodeInfo.mCharacters.length;
+ if (wordPos == wordLen) {
+ // This dictionary already contains the word.
+ Log.e(TAG, "Something went wrong. If the word is already contained, "
+ + " there is no need to insert new PtNode.");
+ return FormatSpec.NOT_VALID_WORD;
+ }
+ if (nodeInfo.mChildrenPos == FormatSpec.NO_CHILDREN_ADDRESS) {
+ // There are no children.
+ // We need to add a new node as a child of this node.
+ final int newNodeArrayPos = mDictBuffer.limit();
+ final int[] newNodeCodePoints = Arrays.copyOfRange(codePoints, wordPos,
+ codePoints.length);
+ writeNewSinglePtNodeWithAttributes(newNodeCodePoints, hasShortcuts,
+ newTerminalId, hasBigrams, isNotAWord, isBlackListEntry, nodePos,
+ header.mFormatOptions);
+ updateChildrenPos(nodePos, newNodeArrayPos, header.mFormatOptions);
+ return newNodeArrayPos + 1 /* size of PtNodeCount */;
+ } else {
+ // Found the matched node.
+ // Go to the children of this node.
+ setPosition(nodeInfo.mChildrenPos);
+ goToChildren = true;
+ depth++;
+ break;
+ }
+ }
+
+ if (goToChildren) continue;
+ if (!readAndFollowForwardLink()) {
+ // Add a new node that contains [wordPos, word.length()-1].
+ // and update the forward link.
+ final int newNodeArrayPos = mDictBuffer.limit();
+ final int[] newCodePoints = Arrays.copyOfRange(codePoints, wordPos,
+ codePoints.length);
+ writeNewSinglePtNodeWithAttributes(newCodePoints, hasShortcuts, newTerminalId,
+ hasBigrams, isNotAWord, isBlackListEntry, parentPos, header.mFormatOptions);
+ updateForwardLink(nodeArrayPos, newNodeArrayPos, header.mFormatOptions);
+ return newNodeArrayPos + 1 /* size of PtNodeCount */;
+ }
+ }
+ return FormatSpec.NOT_VALID_WORD;
+ }
+
+ private void updateFrequency(final int terminalId, final int frequency) {
+ mFrequencyBuffer.position(terminalId * FormatSpec.FREQUENCY_AND_FLAGS_SIZE);
+ BinaryDictEncoderUtils.writeUIntToDictBuffer(mFrequencyBuffer, frequency,
+ FormatSpec.FREQUENCY_AND_FLAGS_SIZE);
+ }
+
+ private void insertFrequency(final int frequency) throws IOException {
+ final OutputStream frequencyStream = new FileOutputStream(mFrequencyFile,
+ true /* append */);
+ BinaryDictEncoderUtils.writeUIntToStream(frequencyStream, frequency,
+ FormatSpec.FREQUENCY_AND_FLAGS_SIZE);
+ frequencyStream.close();
+ }
+
+ private void insertTerminalPosition(final int posOfTerminal) throws IOException {
+ final OutputStream terminalPosStream = new FileOutputStream(
+ getFile(FILETYPE_TERMINAL_ADDRESS_TABLE), true /* append */);
+ BinaryDictEncoderUtils.writeUIntToStream(terminalPosStream, posOfTerminal,
+ FormatSpec.TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE);
+ terminalPosStream.close();
+ }
+
+ private void insertBigrams(final int terminalId, final int frequency,
+ final ArrayList<PendingAttribute> bigramAddresses)
+ throws IOException, UnsupportedFormatException {
+ openDictBuffer();
+ final BigramContentUpdater updater = new BigramContentUpdater(mDictDirectory.getName(),
+ mDictDirectory, false);
+
+ // Convert addresses to terminal ids.
+ final ArrayList<PendingAttribute> bigrams = CollectionUtils.newArrayList();
+ mDictBuffer.position(0);
+ final FileHeader header = readHeader();
+ for (PendingAttribute attr : bigramAddresses) {
+ mDictBuffer.position(attr.mAddress);
+ final Ver4PtNodeInfo info = readVer4PtNodeInfo(attr.mAddress, header.mFormatOptions);
+ if (info.mTerminalId == PtNode.NOT_A_TERMINAL) {
+ throw new RuntimeException("We can't have a bigram target that's not a terminal.");
+ }
+ bigrams.add(new PendingAttribute(frequency, info.mTerminalId));
+ }
+ updater.insertBigramEntries(terminalId, frequency, bigrams);
+ close();
+ }
+
+ private void insertShortcuts(final int terminalId, final ArrayList<WeightedString> shortcuts)
+ throws IOException {
+ final ShortcutContentUpdater updater = new ShortcutContentUpdater(mDictDirectory.getName(),
+ mDictDirectory);
+ updater.insertShortcuts(terminalId, shortcuts);
+ }
+
+ private void openBuffersAndStream() throws IOException {
+ openDictBuffer();
+ mDictStream = new FileOutputStream(getFile(FILETYPE_TRIE), true /* append */);
+ }
+
+ private void close() throws IOException {
+ if (mDictStream != null) {
+ mDictStream.close();
+ mDictStream = null;
+ }
+ mDictBuffer = null;
+ mFrequencyBuffer = null;
+ mTerminalAddressTableBuffer = null;
+ }
+
+ private void updateAttributes(final int posOfWord, final int frequency,
+ final ArrayList<WeightedString> bigramStrings,
+ final ArrayList<WeightedString> shortcuts, final boolean isNotAWord,
+ final boolean isBlackListEntry) throws IOException, UnsupportedFormatException {
+ mDictBuffer.position(0);
+ final FileHeader header = readHeader();
+ mDictBuffer.position(posOfWord);
+ final Ver4PtNodeInfo info = readVer4PtNodeInfo(posOfWord, header.mFormatOptions);
+ final int terminalId = info.mTerminalId;
+
+ // Update the flags.
+ final int newFlags = setIsNotAWordInFlags(
+ setIsBlackListEntryInFlags(info.mFlags, isBlackListEntry), isNotAWord);
+ mDictBuffer.position(posOfWord);
+ mDictBuffer.put((byte) newFlags);
+
+ updateFrequency(terminalId, frequency);
+ insertBigrams(terminalId, frequency,
+ DynamicBinaryDictIOUtils.resolveBigramPositions(this, bigramStrings));
+ insertShortcuts(terminalId, shortcuts);
+ }
+
+ @Override @UsedForTesting
public void insertWord(final String word, final int frequency,
final ArrayList<WeightedString> bigramStrings, final ArrayList<WeightedString> shortcuts,
final boolean isNotAWord, final boolean isBlackListEntry)
throws IOException, UnsupportedFormatException {
- // TODO: Implement this method.
+ final int newTerminalId = getNewTerminalId();
+
+ openBuffersAndStream();
+ final int posOfWord = getTerminalPosition(word);
+ if (posOfWord != FormatSpec.NOT_VALID_WORD) {
+ // The word is already contained in the dictionary.
+ updateAttributes(posOfWord, frequency, bigramStrings, shortcuts, isNotAWord,
+ isBlackListEntry);
+ close();
+ return;
+ }
+
+ // Insert new PtNode into trie.
+ final int posOfTerminal = insertWordToTrie(word, newTerminalId, isNotAWord,
+ isBlackListEntry, bigramStrings != null && !bigramStrings.isEmpty(),
+ shortcuts != null && !shortcuts.isEmpty());
+ insertFrequency(frequency);
+ insertTerminalPosition(posOfTerminal);
+ close();
+
+ insertBigrams(newTerminalId, frequency,
+ DynamicBinaryDictIOUtils.resolveBigramPositions(this, bigramStrings));
+ insertShortcuts(newTerminalId, shortcuts);
}
}
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 102a41b4e..fdbe81ab6 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -197,7 +197,9 @@ public final class SubtypeLocaleUtils {
// es_US spanish F Español (EE.UU.) exception
// fr azerty F Français
// fr_CA qwerty F Français (Canada)
+ // fr_CH swiss F Français (Suisse)
// de qwertz F Deutsch
+ // de_CH swiss T Deutsch (Schweiz)
// zz qwerty F No language (QWERTY) in system locale
// fr qwertz T Français (QWERTZ)
// de qwerty T Deutsch (QWERTY)
@@ -298,7 +300,9 @@ public final class SubtypeLocaleUtils {
// es_US spanish F Es Español Español (EE.UU.) exception
// fr azerty F Fr Français Français
// fr_CA qwerty F Fr Français Français (Canada)
+ // fr_CH swiss F Fr Français Français (Suisse)
// de qwertz F De Deutsch Deutsch
+ // de_CH swiss T De Deutsch Deutsch (Schweiz)
// zz qwerty F QWERTY QWERTY
// fr qwertz T Fr Français Français
// de qwerty T De Deutsch Deutsch
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index da9c61103..ad509923a 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -102,10 +102,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
&& ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
private static final boolean DEBUG_REPLAY_AFTER_FEEDBACK = false
&& ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
- // Whether the TextView contents are logged at the end of the session. true will disclose
- // private info.
- private static final boolean LOG_FULL_TEXTVIEW_CONTENTS = false
- && ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS_DEBUG;
// Whether the feedback dialog preserves the editable text across invocations. Should be false
// for normal research builds so users do not have to delete the same feedback string they
// entered earlier. Should be true for builds internal to a development team so when the text
@@ -168,9 +164,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// U+E001 is in the "private-use area"
/* package for test */ static final String WORD_REPLACEMENT_STRING = "\uE001";
protected static final int SUSPEND_DURATION_IN_MINUTES = 1;
- // set when LatinIME should ignore an onUpdateSelection() callback that
- // arises from operations in this class
- private static boolean sLatinIMEExpectingUpdateSelection = false;
// used to check whether words are not unique
private Suggest mSuggest;
@@ -1126,12 +1119,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
new Object[] { applicationSpecifiedCompletions });
}
- public static boolean getAndClearLatinIMEExpectingUpdateSelection() {
- boolean returnValue = sLatinIMEExpectingUpdateSelection;
- sLatinIMEExpectingUpdateSelection = false;
- return returnValue;
- }
-
/**
* The IME is finishing; it is either being destroyed, or is about to be hidden.
*
@@ -1149,51 +1136,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// if called from finishViews(), which is called from hideWindow() and onDestroy(). These
// are the situations in which we want to finish up the researchLog.
if (ic != null && !finishingInput) {
- final boolean isTextTruncated;
- final String text;
- if (LOG_FULL_TEXTVIEW_CONTENTS) {
- // Capture the TextView contents. This will trigger onUpdateSelection(), so we
- // set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called,
- // it can tell that it was generated by the logging code, and not by the user, and
- // therefore keep user-visible state as is.
- ic.beginBatchEdit();
- ic.performContextMenuAction(android.R.id.selectAll);
- CharSequence charSequence = ic.getSelectedText(0);
- if (savedSelectionStart != -1 && savedSelectionEnd != -1) {
- ic.setSelection(savedSelectionStart, savedSelectionEnd);
- }
- ic.endBatchEdit();
- sLatinIMEExpectingUpdateSelection = true;
- if (TextUtils.isEmpty(charSequence)) {
- isTextTruncated = false;
- text = "";
- } else {
- if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) {
- int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE;
- // do not cut in the middle of a supplementary character
- final char c = charSequence.charAt(length - 1);
- if (Character.isHighSurrogate(c)) {
- length--;
- }
- final CharSequence truncatedCharSequence = charSequence.subSequence(0,
- length);
- isTextTruncated = true;
- text = truncatedCharSequence.toString();
- } else {
- isTextTruncated = false;
- text = charSequence.toString();
- }
- }
- } else {
- isTextTruncated = true;
- text = "";
- }
final ResearchLogger researchLogger = getInstance();
// Assume that OUTPUT_ENTIRE_BUFFER is only true when we don't care about privacy (e.g.
// during a live user test), so the normal isPotentiallyPrivate and
// isPotentiallyRevealing flags do not apply
researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONFINISHINPUTVIEWINTERNAL,
- isTextTruncated, text);
+ true /* isTextTruncated */, "" /* text */);
researchLogger.commitCurrentLogUnit();
getInstance().stop();
}
@@ -1213,9 +1161,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
public static void latinIME_onUpdateSelection(final int lastSelectionStart,
final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd,
final int newSelStart, final int newSelEnd, final int composingSpanStart,
- final int composingSpanEnd, final boolean expectingUpdateSelection,
- final boolean expectingUpdateSelectionFromLogger,
- final RichInputConnection connection) {
+ final int composingSpanEnd, final RichInputConnection connection) {
String word = "";
if (connection != null) {
TextRange range = connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1);
@@ -1227,8 +1173,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
final String scrubbedWord = researchLogger.scrubWord(word);
researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_ONUPDATESELECTION, lastSelectionStart,
lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd,
- composingSpanStart, composingSpanEnd, expectingUpdateSelection,
- expectingUpdateSelectionFromLogger, scrubbedWord);
+ composingSpanStart, composingSpanEnd, false /* expectingUpdateSelection */,
+ false /* expectingUpdateSelectionFromLogger */, scrubbedWord);
}
/**
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index ca6a77997..55a5c06d7 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -57,6 +57,7 @@ LATIN_IME_CORE_SRC_FILES := \
bloom_filter.cpp \
dictionary.cpp \
digraph_utils.cpp \
+ error_type_utils.cpp \
multi_bigram_map.cpp) \
$(addprefix suggest/core/layout/, \
additional_proximity_chars.cpp \
@@ -72,22 +73,28 @@ LATIN_IME_CORE_SRC_FILES := \
header/header_policy.cpp \
header/header_read_write_utils.cpp \
shortcut/shortcut_list_reading_utils.cpp \
- dictionary_structure_with_buffer_policy_factory.cpp \
+ structure/dictionary_structure_with_buffer_policy_factory.cpp) \
+ $(addprefix suggest/policyimpl/dictionary/structure/v2/, \
+ patricia_trie_policy.cpp \
+ patricia_trie_reading_utils.cpp) \
+ $(addprefix suggest/policyimpl/dictionary/structure/v3/, \
dynamic_patricia_trie_gc_event_listeners.cpp \
dynamic_patricia_trie_node_reader.cpp \
dynamic_patricia_trie_policy.cpp \
dynamic_patricia_trie_reading_helper.cpp \
dynamic_patricia_trie_reading_utils.cpp \
dynamic_patricia_trie_writing_helper.cpp \
- dynamic_patricia_trie_writing_utils.cpp \
- patricia_trie_policy.cpp \
- patricia_trie_reading_utils.cpp) \
+ dynamic_patricia_trie_writing_utils.cpp) \
+ $(addprefix suggest/policyimpl/dictionary/structure/v4/, \
+ ver4_dict_constants.cpp \
+ ver4_patricia_trie_policy.cpp) \
$(addprefix suggest/policyimpl/dictionary/utils/, \
buffer_with_extendable_buffer.cpp \
byte_array_utils.cpp \
dict_file_writing_utils.cpp \
forgetting_curve_utils.cpp \
- format_utils.cpp) \
+ format_utils.cpp \
+ mmapped_buffer.cpp) \
suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
$(addprefix suggest/policyimpl/typing/, \
scoring_params.cpp \
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 8f21c50ec..3becc7e39 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -25,7 +25,7 @@
#include "jni_common.h"
#include "suggest/core/dictionary/dictionary.h"
#include "suggest/core/suggest_options.h"
-#include "suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h"
+#include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
#include "utils/autocorrection_threshold_utils.h"
@@ -86,11 +86,11 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring s
char sourceDirChars[sourceDirUtf8Length + 1];
env->GetStringUTFRegion(sourceDir, 0, env->GetStringLength(sourceDir), sourceDirChars);
sourceDirChars[sourceDirUtf8Length] = '\0';
- DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy =
+ DictionaryStructureWithBufferPolicy::StructurePoilcyPtr dictionaryStructureWithBufferPolicy(
DictionaryStructureWithBufferPolicyFactory::newDictionaryStructureWithBufferPolicy(
sourceDirChars, static_cast<int>(dictOffset), static_cast<int>(dictSize),
- isUpdatable == JNI_TRUE);
- if (!dictionaryStructureWithBufferPolicy) {
+ isUpdatable == JNI_TRUE));
+ if (!dictionaryStructureWithBufferPolicy.get()) {
return 0;
}
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 742e388e4..fbcd612b7 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -392,24 +392,4 @@ typedef enum {
// Create new word with space substitution
CT_NEW_WORD_SPACE_SUBSTITUTION,
} CorrectionType;
-
-// ErrorType is mainly decided by CorrectionType but it is also depending on if
-// the correction has really been performed or not.
-typedef enum {
- // Substitution, omission and transposition
- ET_EDIT_CORRECTION,
- // Proximity error
- ET_PROXIMITY_CORRECTION,
- // Completion
- ET_COMPLETION,
- // New word
- // TODO: Remove.
- // A new word error should be an edit correction error or a proximity correction error.
- ET_NEW_WORD,
- // Treat error as an intentional omission when the CorrectionType is omission and the node can
- // be intentional omission.
- ET_INTENTIONAL_OMISSION,
- // Not treated as an error. Tracked for checking exact match
- ET_NOT_AN_ERROR
-} ErrorType;
#endif // LATINIME_DEFINES_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index 49cfdecac..0b2b4a9e8 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -99,7 +99,7 @@ class DicNode {
virtual ~DicNode() {}
// Init for copy
- void initByCopy(const DicNode *dicNode) {
+ void initByCopy(const DicNode *const dicNode) {
mIsUsed = true;
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
mDicNodeProperties.init(&dicNode->mDicNodeProperties);
@@ -107,25 +107,25 @@ class DicNode {
PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
}
- // Init for root with prevWordNodePos which is used for bigram
- void initAsRoot(const int rootGroupPos, const int prevWordNodePos) {
+ // Init for root with prevWordPtNodePos which is used for bigram
+ void initAsRoot(const int rootPtNodeArrayPos, const int prevWordPtNodePos) {
mIsUsed = true;
mIsCachedForNextSuggestion = false;
mDicNodeProperties.init(
- NOT_A_DICT_POS /* pos */, rootGroupPos, NOT_A_CODE_POINT /* nodeCodePoint */,
+ NOT_A_DICT_POS /* pos */, rootPtNodeArrayPos, NOT_A_CODE_POINT /* nodeCodePoint */,
NOT_A_PROBABILITY /* probability */, false /* isTerminal */,
true /* hasChildren */, false /* isBlacklistedOrNotAWord */, 0 /* depth */,
0 /* terminalDepth */);
- mDicNodeState.init(prevWordNodePos);
+ mDicNodeState.init(prevWordPtNodePos);
PROF_NODE_RESET(mProfiler);
}
// Init for root with previous word
- void initAsRootWithPreviousWord(DicNode *dicNode, const int rootGroupPos) {
+ void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
mIsUsed = true;
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
mDicNodeProperties.init(
- NOT_A_DICT_POS /* pos */, rootGroupPos, NOT_A_CODE_POINT /* nodeCodePoint */,
+ NOT_A_DICT_POS /* pos */, rootPtNodeArrayPos, NOT_A_CODE_POINT /* nodeCodePoint */,
NOT_A_PROBABILITY /* probability */, false /* isTerminal */,
true /* hasChildren */, false /* isBlacklistedOrNotAWord */, 0 /* depth */,
0 /* terminalDepth */);
@@ -138,7 +138,7 @@ class DicNode {
mDicNodeState.mDicNodeStatePrevWord.init(
dicNode->mDicNodeState.mDicNodeStatePrevWord.getPrevWordCount() + 1,
dicNode->mDicNodeProperties.getProbability(),
- dicNode->mDicNodeProperties.getPos(),
+ dicNode->mDicNodeProperties.getPtNodePos(),
dicNode->mDicNodeState.mDicNodeStatePrevWord.mPrevWord,
dicNode->mDicNodeState.mDicNodeStatePrevWord.getPrevWordLength(),
dicNode->getOutputWordBuf(),
@@ -148,26 +148,27 @@ class DicNode {
PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
}
- void initAsPassingChild(DicNode *parentNode) {
+ void initAsPassingChild(DicNode *parentDicNode) {
mIsUsed = true;
- mIsCachedForNextSuggestion = parentNode->mIsCachedForNextSuggestion;
- const int c = parentNode->getNodeTypedCodePoint();
- mDicNodeProperties.init(&parentNode->mDicNodeProperties, c);
- mDicNodeState.init(&parentNode->mDicNodeState);
- PROF_NODE_COPY(&parentNode->mProfiler, mProfiler);
+ mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion;
+ const int parentCodePoint = parentDicNode->getNodeTypedCodePoint();
+ mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, parentCodePoint);
+ mDicNodeState.init(&parentDicNode->mDicNodeState);
+ PROF_NODE_COPY(&parentDicNode->mProfiler, mProfiler);
}
- void initAsChild(const DicNode *const dicNode, const int pos, const int childrenPos,
- const int probability, const bool isTerminal, const bool hasChildren,
- const bool isBlacklistedOrNotAWord, const uint16_t mergedNodeCodePointCount,
- const int *const mergedNodeCodePoints) {
+ void initAsChild(const DicNode *const dicNode, const int ptNodePos,
+ const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
+ const bool hasChildren, const bool isBlacklistedOrNotAWord,
+ const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
mIsUsed = true;
uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
const uint16_t newLeavingDepth = static_cast<uint16_t>(
dicNode->mDicNodeProperties.getLeavingDepth() + mergedNodeCodePointCount);
- mDicNodeProperties.init(pos, childrenPos, mergedNodeCodePoints[0], probability,
- isTerminal, hasChildren, isBlacklistedOrNotAWord, newDepth, newLeavingDepth);
+ mDicNodeProperties.init(ptNodePos, childrenPtNodeArrayPos, mergedNodeCodePoints[0],
+ probability, isTerminal, hasChildren, isBlacklistedOrNotAWord, newDepth,
+ newLeavingDepth);
mDicNodeState.init(&dicNode->mDicNodeState, mergedNodeCodePointCount,
mergedNodeCodePoints);
PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
@@ -234,7 +235,7 @@ class DicNode {
}
bool isFirstWord() const {
- return mDicNodeState.mDicNodeStatePrevWord.getPrevWordNodePos() == NOT_A_DICT_POS;
+ return mDicNodeState.mDicNodeStatePrevWord.getPrevWordPtNodePos() == NOT_A_DICT_POS;
}
bool isCompletion(const int inputSize) const {
@@ -246,29 +247,30 @@ class DicNode {
}
// Used to get bigram probability in DicNodeUtils
- int getPos() const {
- return mDicNodeProperties.getPos();
+ int getPtNodePos() const {
+ return mDicNodeProperties.getPtNodePos();
}
// Used to get bigram probability in DicNodeUtils
- int getPrevWordPos() const {
- return mDicNodeState.mDicNodeStatePrevWord.getPrevWordNodePos();
+ int getPrevWordTerminalPtNodePos() const {
+ return mDicNodeState.mDicNodeStatePrevWord.getPrevWordPtNodePos();
}
// Used in DicNodeUtils
- int getChildrenPos() const {
- return mDicNodeProperties.getChildrenPos();
+ int getChildrenPtNodeArrayPos() const {
+ return mDicNodeProperties.getChildrenPtNodeArrayPos();
}
int getProbability() const {
return mDicNodeProperties.getProbability();
}
- AK_FORCE_INLINE bool isTerminalWordNode() const {
- const bool isTerminalNodes = mDicNodeProperties.isTerminal();
- const int currentNodeDepth = getNodeCodePointCount();
- const int terminalNodeDepth = mDicNodeProperties.getLeavingDepth();
- return isTerminalNodes && currentNodeDepth > 0 && currentNodeDepth == terminalNodeDepth;
+ AK_FORCE_INLINE bool isTerminalDicNode() const {
+ const bool isTerminalPtNode = mDicNodeProperties.isTerminal();
+ const int currentDicNodeDepth = getNodeCodePointCount();
+ const int terminalDicNodeDepth = mDicNodeProperties.getLeavingDepth();
+ return isTerminalPtNode && currentDicNodeDepth > 0
+ && currentDicNodeDepth == terminalDicNodeDepth;
}
bool shouldBeFilteredBySafetyNetForBigram() const {
@@ -374,8 +376,8 @@ class DicNode {
}
// Used to commit input partially
- int getPrevWordNodePos() const {
- return mDicNodeState.mDicNodeStatePrevWord.getPrevWordNodePos();
+ int getPrevWordPtNodePos() const {
+ return mDicNodeState.mDicNodeStatePrevWord.getPrevWordPtNodePos();
}
AK_FORCE_INLINE const int *getOutputWordBuf() const {
@@ -410,7 +412,7 @@ class DicNode {
// TODO: Remove once touch path is merged into ProximityInfoState
// Note: Returned codepoint may be a digraph codepoint if the node is in a composite glyph.
int getNodeCodePoint() const {
- const int codePoint = mDicNodeProperties.getNodeCodePoint();
+ const int codePoint = mDicNodeProperties.getDicNodeCodePoint();
const DigraphUtils::DigraphCodePointIndex digraphIndex =
mDicNodeState.mDicNodeStateScoring.getDigraphIndex();
if (digraphIndex == DigraphUtils::NOT_A_DIGRAPH_INDEX) {
@@ -423,8 +425,8 @@ class DicNode {
// Utils for cost calculation //
////////////////////////////////
AK_FORCE_INLINE bool isSameNodeCodePoint(const DicNode *const dicNode) const {
- return mDicNodeProperties.getNodeCodePoint()
- == dicNode->mDicNodeProperties.getNodeCodePoint();
+ return mDicNodeProperties.getDicNodeCodePoint()
+ == dicNode->mDicNodeProperties.getDicNodeCodePoint();
}
// TODO: remove
@@ -574,7 +576,8 @@ class DicNode {
// Caveat: Must not be called outside Weighting
// This restriction is guaranteed by "friend"
AK_FORCE_INLINE void addCost(const float spatialCost, const float languageCost,
- const bool doNormalization, const int inputSize, const ErrorType errorType) {
+ const bool doNormalization, const int inputSize,
+ const ErrorTypeUtils::ErrorType errorType) {
if (DEBUG_GEO_FULL) {
LOGI_SHOW_ADD_COST_PROP;
}
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index ec65114c7..5540b6df5 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -22,7 +22,6 @@
#include "suggest/core/dicnode/dic_node_vector.h"
#include "suggest/core/dictionary/multi_bigram_map.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "utils/char_utils.h"
namespace latinime {
@@ -32,19 +31,20 @@ namespace latinime {
/* static */ void DicNodeUtils::initAsRoot(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- const int prevWordNodePos, DicNode *const newRootNode) {
- newRootNode->initAsRoot(dictionaryStructurePolicy->getRootPosition(), prevWordNodePos);
+ const int prevWordPtNodePos, DicNode *const newRootDicNode) {
+ newRootDicNode->initAsRoot(dictionaryStructurePolicy->getRootPosition(), prevWordPtNodePos);
}
/*static */ void DicNodeUtils::initAsRootWithPreviousWord(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- DicNode *const prevWordLastNode, DicNode *const newRootNode) {
- newRootNode->initAsRootWithPreviousWord(
- prevWordLastNode, dictionaryStructurePolicy->getRootPosition());
+ const DicNode *const prevWordLastDicNode, DicNode *const newRootDicNode) {
+ newRootDicNode->initAsRootWithPreviousWord(
+ prevWordLastDicNode, dictionaryStructurePolicy->getRootPosition());
}
-/* static */ void DicNodeUtils::initByCopy(DicNode *srcNode, DicNode *destNode) {
- destNode->initByCopy(srcNode);
+/* static */ void DicNodeUtils::initByCopy(const DicNode *const srcDicNode,
+ DicNode *const destDicNode) {
+ destDicNode->initByCopy(srcDicNode);
}
///////////////////////////////////
@@ -52,14 +52,14 @@ namespace latinime {
///////////////////////////////////
/* static */ void DicNodeUtils::getAllChildDicNodes(DicNode *dicNode,
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- DicNodeVector *childDicNodes) {
+ DicNodeVector *const childDicNodes) {
if (dicNode->isTotalInputSizeExceedingLimit()) {
return;
}
if (!dicNode->isLeavingNode()) {
childDicNodes->pushPassingChild(dicNode);
} else {
- dictionaryStructurePolicy->createAndGetAllChildNodes(dicNode, childDicNodes);
+ dictionaryStructurePolicy->createAndGetAllChildDicNodes(dicNode, childDicNodes);
}
}
@@ -71,11 +71,11 @@ namespace latinime {
*/
/* static */ float DicNodeUtils::getBigramNodeImprobability(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- const DicNode *const node, MultiBigramMap *multiBigramMap) {
- if (node->hasMultipleWords() && !node->isValidMultipleWordSuggestion()) {
+ const DicNode *const dicNode, MultiBigramMap *const multiBigramMap) {
+ if (dicNode->hasMultipleWords() && !dicNode->isValidMultipleWordSuggestion()) {
return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
}
- const int probability = getBigramNodeProbability(dictionaryStructurePolicy, node,
+ const int probability = getBigramNodeProbability(dictionaryStructurePolicy, dicNode,
multiBigramMap);
// TODO: This equation to calculate the improbability looks unreasonable. Investigate this.
const float cost = static_cast<float>(MAX_PROBABILITY - probability)
@@ -85,19 +85,19 @@ namespace latinime {
/* static */ int DicNodeUtils::getBigramNodeProbability(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- const DicNode *const node, MultiBigramMap *multiBigramMap) {
- const int unigramProbability = node->getProbability();
- const int wordPos = node->getPos();
- const int prevWordPos = node->getPrevWordPos();
- if (NOT_A_DICT_POS == wordPos || NOT_A_DICT_POS == prevWordPos) {
+ const DicNode *const dicNode, MultiBigramMap *const multiBigramMap) {
+ const int unigramProbability = dicNode->getProbability();
+ const int ptNodePos = dicNode->getPtNodePos();
+ const int prevWordTerminalPtNodePos = dicNode->getPrevWordTerminalPtNodePos();
+ if (NOT_A_DICT_POS == ptNodePos || NOT_A_DICT_POS == prevWordTerminalPtNodePos) {
// Note: Normally wordPos comes from the dictionary and should never equal
// NOT_A_VALID_WORD_POS.
return dictionaryStructurePolicy->getProbability(unigramProbability,
NOT_A_PROBABILITY);
}
if (multiBigramMap) {
- return multiBigramMap->getBigramProbability(dictionaryStructurePolicy, prevWordPos,
- wordPos, unigramProbability);
+ return multiBigramMap->getBigramProbability(dictionaryStructurePolicy,
+ prevWordTerminalPtNodePos, ptNodePos, unigramProbability);
}
return dictionaryStructurePolicy->getProbability(unigramProbability,
NOT_A_PROBABILITY);
@@ -109,7 +109,7 @@ namespace latinime {
// TODO: Move to char_utils?
/* static */ int DicNodeUtils::appendTwoWords(const int *const src0, const int16_t length0,
- const int *const src1, const int16_t length1, int *dest) {
+ const int *const src1, const int16_t length1, int *const dest) {
int actualLength0 = 0;
for (int i = 0; i < length0; ++i) {
if (src0[i] == 0) {
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.h b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
index 3fb351a61..3f1514a52 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
@@ -31,20 +31,20 @@ class MultiBigramMap;
class DicNodeUtils {
public:
static int appendTwoWords(const int *src0, const int16_t length0, const int *src1,
- const int16_t length1, int *dest);
+ const int16_t length1, int *const dest);
static void initAsRoot(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- const int prevWordNodePos, DicNode *newRootNode);
+ const int prevWordPtNodePos, DicNode *const newRootDicNode);
static void initAsRootWithPreviousWord(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- DicNode *prevWordLastNode, DicNode *newRootNode);
- static void initByCopy(DicNode *srcNode, DicNode *destNode);
+ const DicNode *const prevWordLastDicNode, DicNode *const newRootDicNode);
+ static void initByCopy(const DicNode *const srcDicNode, DicNode *const destDicNode);
static void getAllChildDicNodes(DicNode *dicNode,
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
DicNodeVector *childDicNodes);
static float getBigramNodeImprobability(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- const DicNode *const node, MultiBigramMap *const multiBigramMap);
+ const DicNode *const dicNode, MultiBigramMap *const multiBigramMap);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodeUtils);
@@ -53,7 +53,7 @@ class DicNodeUtils {
static int getBigramNodeProbability(
const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
- const DicNode *const node, MultiBigramMap *multiBigramMap);
+ const DicNode *const dicNode, MultiBigramMap *const multiBigramMap);
};
} // namespace latinime
#endif // LATINIME_DIC_NODE_UTILS_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_vector.h b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
index 42addae8d..9364e7751 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_vector.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
@@ -62,14 +62,14 @@ class DicNodeVector {
mDicNodes.back().initAsPassingChild(dicNode);
}
- void pushLeavingChild(const DicNode *const dicNode, const int pos, const int childrenPos,
- const int probability, const bool isTerminal, const bool hasChildren,
- const bool isBlacklistedOrNotAWord, const uint16_t mergedNodeCodePointCount,
- const int *const mergedNodeCodePoints) {
+ void pushLeavingChild(const DicNode *const dicNode, const int ptNodePos,
+ const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
+ const bool hasChildren, const bool isBlacklistedOrNotAWord,
+ const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
ASSERT(!mLock);
mDicNodes.push_back(mEmptyNode);
- mDicNodes.back().initAsChild(dicNode, pos, childrenPos, probability, isTerminal,
- hasChildren, isBlacklistedOrNotAWord, mergedNodeCodePointCount,
+ mDicNodes.back().initAsChild(dicNode, ptNodePos, childrenPtNodeArrayPos, probability,
+ isTerminal, hasChildren, isBlacklistedOrNotAWord, mergedNodeCodePointCount,
mergedNodeCodePoints);
}
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
index 9e0f62ceb..c41a7243a 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
@@ -24,15 +24,14 @@
namespace latinime {
/**
- * Node for traversing the lexicon trie.
+ * PtNode information related to the DicNode from the lexicon trie.
*/
-// TODO: Introduce a dictionary node class which has attribute members required to understand the
-// dictionary structure.
class DicNodeProperties {
public:
AK_FORCE_INLINE DicNodeProperties()
- : mPos(0), mChildrenPos(0), mProbability(0), mNodeCodePoint(0), mIsTerminal(false),
- mHasChildren(false), mIsBlacklistedOrNotAWord(false), mDepth(0), mLeavingDepth(0) {}
+ : mPtNodePos(0), mChildrenPtNodeArrayPos(0), mProbability(0), mDicNodeCodePoint(0),
+ mIsTerminal(false), mHasChildrenPtNodes(false), mIsBlacklistedOrNotAWord(false),
+ mDepth(0), mLeavingDepth(0) {}
virtual ~DicNodeProperties() {}
@@ -40,57 +39,57 @@ class DicNodeProperties {
void init(const int pos, const int childrenPos, const int nodeCodePoint, const int probability,
const bool isTerminal, const bool hasChildren, const bool isBlacklistedOrNotAWord,
const uint16_t depth, const uint16_t leavingDepth) {
- mPos = pos;
- mChildrenPos = childrenPos;
- mNodeCodePoint = nodeCodePoint;
+ mPtNodePos = pos;
+ mChildrenPtNodeArrayPos = childrenPos;
+ mDicNodeCodePoint = nodeCodePoint;
mProbability = probability;
mIsTerminal = isTerminal;
- mHasChildren = hasChildren;
+ mHasChildrenPtNodes = hasChildren;
mIsBlacklistedOrNotAWord = isBlacklistedOrNotAWord;
mDepth = depth;
mLeavingDepth = leavingDepth;
}
// Init for copy
- void init(const DicNodeProperties *const nodeProp) {
- mPos = nodeProp->mPos;
- mChildrenPos = nodeProp->mChildrenPos;
- mNodeCodePoint = nodeProp->mNodeCodePoint;
- mProbability = nodeProp->mProbability;
- mIsTerminal = nodeProp->mIsTerminal;
- mHasChildren = nodeProp->mHasChildren;
- mIsBlacklistedOrNotAWord = nodeProp->mIsBlacklistedOrNotAWord;
- mDepth = nodeProp->mDepth;
- mLeavingDepth = nodeProp->mLeavingDepth;
+ void init(const DicNodeProperties *const dicNodeProp) {
+ mPtNodePos = dicNodeProp->mPtNodePos;
+ mChildrenPtNodeArrayPos = dicNodeProp->mChildrenPtNodeArrayPos;
+ mDicNodeCodePoint = dicNodeProp->mDicNodeCodePoint;
+ mProbability = dicNodeProp->mProbability;
+ mIsTerminal = dicNodeProp->mIsTerminal;
+ mHasChildrenPtNodes = dicNodeProp->mHasChildrenPtNodes;
+ mIsBlacklistedOrNotAWord = dicNodeProp->mIsBlacklistedOrNotAWord;
+ mDepth = dicNodeProp->mDepth;
+ mLeavingDepth = dicNodeProp->mLeavingDepth;
}
// Init as passing child
- void init(const DicNodeProperties *const nodeProp, const int codePoint) {
- mPos = nodeProp->mPos;
- mChildrenPos = nodeProp->mChildrenPos;
- mNodeCodePoint = codePoint; // Overwrite the node char of a passing child
- mProbability = nodeProp->mProbability;
- mIsTerminal = nodeProp->mIsTerminal;
- mHasChildren = nodeProp->mHasChildren;
- mIsBlacklistedOrNotAWord = nodeProp->mIsBlacklistedOrNotAWord;
- mDepth = nodeProp->mDepth + 1; // Increment the depth of a passing child
- mLeavingDepth = nodeProp->mLeavingDepth;
+ void init(const DicNodeProperties *const dicNodeProp, const int codePoint) {
+ mPtNodePos = dicNodeProp->mPtNodePos;
+ mChildrenPtNodeArrayPos = dicNodeProp->mChildrenPtNodeArrayPos;
+ mDicNodeCodePoint = codePoint; // Overwrite the node char of a passing child
+ mProbability = dicNodeProp->mProbability;
+ mIsTerminal = dicNodeProp->mIsTerminal;
+ mHasChildrenPtNodes = dicNodeProp->mHasChildrenPtNodes;
+ mIsBlacklistedOrNotAWord = dicNodeProp->mIsBlacklistedOrNotAWord;
+ mDepth = dicNodeProp->mDepth + 1; // Increment the depth of a passing child
+ mLeavingDepth = dicNodeProp->mLeavingDepth;
}
- int getPos() const {
- return mPos;
+ int getPtNodePos() const {
+ return mPtNodePos;
}
- int getChildrenPos() const {
- return mChildrenPos;
+ int getChildrenPtNodeArrayPos() const {
+ return mChildrenPtNodeArrayPos;
}
int getProbability() const {
return mProbability;
}
- int getNodeCodePoint() const {
- return mNodeCodePoint;
+ int getDicNodeCodePoint() const {
+ return mDicNodeCodePoint;
}
uint16_t getDepth() const {
@@ -107,7 +106,7 @@ class DicNodeProperties {
}
bool hasChildren() const {
- return mHasChildren || mDepth != mLeavingDepth;
+ return mHasChildrenPtNodes || mDepth != mLeavingDepth;
}
bool isBlacklistedOrNotAWord() const {
@@ -118,12 +117,12 @@ class DicNodeProperties {
// Caution!!!
// Use a default copy constructor and an assign operator because shallow copies are ok
// for this class
- int mPos;
- int mChildrenPos;
+ int mPtNodePos;
+ int mChildrenPtNodeArrayPos;
int mProbability;
- int mNodeCodePoint;
+ int mDicNodeCodePoint;
bool mIsTerminal;
- bool mHasChildren;
+ bool mHasChildrenPtNodes;
bool mIsBlacklistedOrNotAWord;
uint16_t mDepth;
uint16_t mLeavingDepth;
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
index b8986203d..dba57056b 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_prevword.h
@@ -30,7 +30,7 @@ class DicNodeStatePrevWord {
public:
AK_FORCE_INLINE DicNodeStatePrevWord()
: mPrevWordCount(0), mPrevWordLength(0), mPrevWordStart(0), mPrevWordProbability(0),
- mPrevWordNodePos(NOT_A_DICT_POS), mSecondWordFirstInputIndex(NOT_AN_INDEX) {
+ mPrevWordPtNodePos(NOT_A_DICT_POS), mSecondWordFirstInputIndex(NOT_AN_INDEX) {
memset(mPrevWord, 0, sizeof(mPrevWord));
}
@@ -41,7 +41,7 @@ class DicNodeStatePrevWord {
mPrevWordCount = 0;
mPrevWordStart = 0;
mPrevWordProbability = -1;
- mPrevWordNodePos = NOT_A_DICT_POS;
+ mPrevWordPtNodePos = NOT_A_DICT_POS;
mSecondWordFirstInputIndex = NOT_AN_INDEX;
}
@@ -50,7 +50,7 @@ class DicNodeStatePrevWord {
mPrevWordCount = 0;
mPrevWordStart = 0;
mPrevWordProbability = -1;
- mPrevWordNodePos = prevWordNodePos;
+ mPrevWordPtNodePos = prevWordNodePos;
mSecondWordFirstInputIndex = NOT_AN_INDEX;
}
@@ -60,7 +60,7 @@ class DicNodeStatePrevWord {
mPrevWordCount = prevWord->mPrevWordCount;
mPrevWordStart = prevWord->mPrevWordStart;
mPrevWordProbability = prevWord->mPrevWordProbability;
- mPrevWordNodePos = prevWord->mPrevWordNodePos;
+ mPrevWordPtNodePos = prevWord->mPrevWordPtNodePos;
mSecondWordFirstInputIndex = prevWord->mSecondWordFirstInputIndex;
memcpy(mPrevWord, prevWord->mPrevWord, prevWord->mPrevWordLength * sizeof(mPrevWord[0]));
}
@@ -71,7 +71,7 @@ class DicNodeStatePrevWord {
const int prevWordSecondWordFirstInputIndex, const int lastInputIndex) {
mPrevWordCount = min(prevWordCount, static_cast<int16_t>(MAX_RESULTS));
mPrevWordProbability = prevWordProbability;
- mPrevWordNodePos = prevWordNodePos;
+ mPrevWordPtNodePos = prevWordNodePos;
int twoWordsLen =
DicNodeUtils::appendTwoWords(src0, length0, src1, length1, mPrevWord);
if (twoWordsLen >= MAX_WORD_LENGTH) {
@@ -116,8 +116,8 @@ class DicNodeStatePrevWord {
return mPrevWordStart;
}
- int getPrevWordNodePos() const {
- return mPrevWordNodePos;
+ int getPrevWordPtNodePos() const {
+ return mPrevWordPtNodePos;
}
int getPrevWordCodePointAt(const int id) const {
@@ -147,7 +147,7 @@ class DicNodeStatePrevWord {
int16_t mPrevWordLength;
int16_t mPrevWordStart;
int16_t mPrevWordProbability;
- int mPrevWordNodePos;
+ int mPrevWordPtNodePos;
int mSecondWordFirstInputIndex;
};
} // namespace latinime
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
index 3c85d0e9d..74f9eee92 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
@@ -21,6 +21,7 @@
#include "defines.h"
#include "suggest/core/dictionary/digraph_utils.h"
+#include "suggest/core/dictionary/error_type_utils.h"
namespace latinime {
@@ -31,7 +32,7 @@ class DicNodeStateScoring {
mDigraphIndex(DigraphUtils::NOT_A_DIGRAPH_INDEX),
mEditCorrectionCount(0), mProximityCorrectionCount(0),
mNormalizedCompoundDistance(0.0f), mSpatialDistance(0.0f), mLanguageDistance(0.0f),
- mRawLength(0.0f), mExactMatch(true),
+ mRawLength(0.0f), mContainingErrorTypes(ErrorTypeUtils::NOT_AN_ERROR),
mNormalizedCompoundDistanceAfterFirstWord(MAX_VALUE_FOR_WEIGHTING) {
}
@@ -47,7 +48,7 @@ class DicNodeStateScoring {
mDoubleLetterLevel = NOT_A_DOUBLE_LETTER;
mDigraphIndex = DigraphUtils::NOT_A_DIGRAPH_INDEX;
mNormalizedCompoundDistanceAfterFirstWord = MAX_VALUE_FOR_WEIGHTING;
- mExactMatch = true;
+ mContainingErrorTypes = ErrorTypeUtils::NOT_AN_ERROR;
}
AK_FORCE_INLINE void init(const DicNodeStateScoring *const scoring) {
@@ -59,34 +60,21 @@ class DicNodeStateScoring {
mRawLength = scoring->mRawLength;
mDoubleLetterLevel = scoring->mDoubleLetterLevel;
mDigraphIndex = scoring->mDigraphIndex;
- mExactMatch = scoring->mExactMatch;
+ mContainingErrorTypes = scoring->mContainingErrorTypes;
mNormalizedCompoundDistanceAfterFirstWord =
scoring->mNormalizedCompoundDistanceAfterFirstWord;
}
void addCost(const float spatialCost, const float languageCost, const bool doNormalization,
- const int inputSize, const int totalInputIndex, const ErrorType errorType) {
+ const int inputSize, const int totalInputIndex,
+ const ErrorTypeUtils::ErrorType errorType) {
addDistance(spatialCost, languageCost, doNormalization, inputSize, totalInputIndex);
- switch (errorType) {
- case ET_EDIT_CORRECTION:
- ++mEditCorrectionCount;
- mExactMatch = false;
- break;
- case ET_PROXIMITY_CORRECTION:
- ++mProximityCorrectionCount;
- mExactMatch = false;
- break;
- case ET_COMPLETION:
- mExactMatch = false;
- break;
- case ET_NEW_WORD:
- mExactMatch = false;
- break;
- case ET_INTENTIONAL_OMISSION:
- mExactMatch = false;
- break;
- case ET_NOT_AN_ERROR:
- break;
+ mContainingErrorTypes = mContainingErrorTypes | errorType;
+ if (ErrorTypeUtils::isEditCorrectionError(errorType)) {
+ ++mEditCorrectionCount;
+ }
+ if (ErrorTypeUtils::isProximityCorrectionError(errorType)) {
+ ++mProximityCorrectionCount;
}
}
@@ -182,7 +170,7 @@ class DicNodeStateScoring {
}
bool isExactMatch() const {
- return mExactMatch;
+ return ErrorTypeUtils::isExactMatch(mContainingErrorTypes);
}
private:
@@ -199,7 +187,8 @@ class DicNodeStateScoring {
float mSpatialDistance;
float mLanguageDistance;
float mRawLength;
- bool mExactMatch;
+ // All accumulated error types so far
+ ErrorTypeUtils::ErrorType mContainingErrorTypes;
float mNormalizedCompoundDistanceAfterFirstWord;
AK_FORCE_INLINE void addDistance(float spatialDistance, float languageDistance,
diff --git a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
index 71f4ef6ea..c2a15a312 100644
--- a/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/bigram_dictionary.cpp
@@ -144,7 +144,7 @@ int BigramDictionary::getPredictions(const int *prevWord, const int prevWordLeng
int BigramDictionary::getBigramListPositionForWord(const int *prevWord, const int prevWordLength,
const bool forceLowerCaseSearch) const {
if (0 >= prevWordLength) return NOT_A_DICT_POS;
- int pos = mDictionaryStructurePolicy->getTerminalNodePositionOfWord(prevWord, prevWordLength,
+ int pos = mDictionaryStructurePolicy->getTerminalPtNodePositionOfWord(prevWord, prevWordLength,
forceLowerCaseSearch);
if (NOT_A_DICT_POS == pos) return NOT_A_DICT_POS;
return mDictionaryStructurePolicy->getBigramsPositionOfPtNode(pos);
@@ -155,7 +155,7 @@ int BigramDictionary::getBigramProbability(const int *word0, int length0, const
int pos = getBigramListPositionForWord(word0, length0, false /* forceLowerCaseSearch */);
// getBigramListPositionForWord returns 0 if this word isn't in the dictionary or has no bigrams
if (NOT_A_DICT_POS == pos) return NOT_A_PROBABILITY;
- int nextWordPos = mDictionaryStructurePolicy->getTerminalNodePositionOfWord(word1, length1,
+ int nextWordPos = mDictionaryStructurePolicy->getTerminalPtNodePositionOfWord(word1, length1,
false /* forceLowerCaseSearch */);
if (NOT_A_DICT_POS == nextWordPos) return NOT_A_PROBABILITY;
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index 59ead1894..7b83f27df 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -21,9 +21,7 @@
#include <stdint.h>
#include "defines.h"
-#include "suggest/core/dictionary/bigram_dictionary.h"
#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
#include "suggest/core/session/dic_traverse_session.h"
#include "suggest/core/suggest.h"
#include "suggest/core/suggest_options.h"
@@ -35,22 +33,15 @@ namespace latinime {
const int Dictionary::HEADER_ATTRIBUTE_BUFFER_SIZE = 32;
-Dictionary::Dictionary(JNIEnv *env,
- DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy)
+Dictionary::Dictionary(JNIEnv *env, const DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
+ &dictionaryStructureWithBufferPolicy)
: mDictionaryStructureWithBufferPolicy(dictionaryStructureWithBufferPolicy),
- mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy)),
+ mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy.get())),
mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
logDictionaryInfo(env);
}
-Dictionary::~Dictionary() {
- delete mBigramDictionary;
- delete mGestureSuggest;
- delete mTypingSuggest;
- delete mDictionaryStructureWithBufferPolicy;
-}
-
int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint,
@@ -60,7 +51,7 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession
if (suggestOptions->isGesture()) {
DicTraverseSession::initSessionInstance(
traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
- result = mGestureSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
+ result = mGestureSuggest.get()->getSuggestions(proximityInfo, traverseSession, xcoordinates,
ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, outWords,
frequencies, spaceIndices, outputTypes, outputAutoCommitFirstWordConfidence);
if (DEBUG_DICT) {
@@ -70,7 +61,7 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession
} else {
DicTraverseSession::initSessionInstance(
traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
- result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
+ result = mTypingSuggest.get()->getSuggestions(proximityInfo, traverseSession, xcoordinates,
ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
outWords, frequencies, spaceIndices, outputTypes,
outputAutoCommitFirstWordConfidence);
@@ -84,11 +75,12 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession
int Dictionary::getBigrams(const int *word, int length, int *outWords, int *frequencies,
int *outputTypes) const {
if (length <= 0) return 0;
- return mBigramDictionary->getPredictions(word, length, outWords, frequencies, outputTypes);
+ return mBigramDictionary.get()->getPredictions(word, length, outWords, frequencies,
+ outputTypes);
}
int Dictionary::getProbability(const int *word, int length) const {
- int pos = getDictionaryStructurePolicy()->getTerminalNodePositionOfWord(word, length,
+ int pos = getDictionaryStructurePolicy()->getTerminalPtNodePositionOfWord(word, length,
false /* forceLowerCaseSearch */);
if (NOT_A_DICT_POS == pos) {
return NOT_A_PROBABILITY;
@@ -98,39 +90,39 @@ int Dictionary::getProbability(const int *word, int length) const {
int Dictionary::getBigramProbability(const int *word0, int length0, const int *word1,
int length1) const {
- return mBigramDictionary->getBigramProbability(word0, length0, word1, length1);
+ return mBigramDictionary.get()->getBigramProbability(word0, length0, word1, length1);
}
void Dictionary::addUnigramWord(const int *const word, const int length, const int probability) {
- mDictionaryStructureWithBufferPolicy->addUnigramWord(word, length, probability);
+ mDictionaryStructureWithBufferPolicy.get()->addUnigramWord(word, length, probability);
}
void Dictionary::addBigramWords(const int *const word0, const int length0, const int *const word1,
const int length1, const int probability) {
- mDictionaryStructureWithBufferPolicy->addBigramWords(word0, length0, word1, length1,
+ mDictionaryStructureWithBufferPolicy.get()->addBigramWords(word0, length0, word1, length1,
probability);
}
void Dictionary::removeBigramWords(const int *const word0, const int length0,
const int *const word1, const int length1) {
- mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1);
+ mDictionaryStructureWithBufferPolicy.get()->removeBigramWords(word0, length0, word1, length1);
}
void Dictionary::flush(const char *const filePath) {
- mDictionaryStructureWithBufferPolicy->flush(filePath);
+ mDictionaryStructureWithBufferPolicy.get()->flush(filePath);
}
void Dictionary::flushWithGC(const char *const filePath) {
- mDictionaryStructureWithBufferPolicy->flushWithGC(filePath);
+ mDictionaryStructureWithBufferPolicy.get()->flushWithGC(filePath);
}
bool Dictionary::needsToRunGC(const bool mindsBlockByGC) {
- return mDictionaryStructureWithBufferPolicy->needsToRunGC(mindsBlockByGC);
+ return mDictionaryStructureWithBufferPolicy.get()->needsToRunGC(mindsBlockByGC);
}
void Dictionary::getProperty(const char *const query, char *const outResult,
const int maxResultLength) {
- return mDictionaryStructureWithBufferPolicy->getProperty(query, outResult, maxResultLength);
+ return mDictionaryStructureWithBufferPolicy.get()->getProperty(query, outResult, maxResultLength);
}
void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index 0195d5bf0..e52a40f1d 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -21,14 +21,16 @@
#include "defines.h"
#include "jni.h"
+#include "suggest/core/dictionary/bigram_dictionary.h"
+#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "suggest/core/suggest_interface.h"
+#include "utils/exclusive_ownership_pointer.h"
namespace latinime {
-class BigramDictionary;
class DictionaryStructureWithBufferPolicy;
class DicTraverseSession;
class ProximityInfo;
-class SuggestInterface;
class SuggestOptions;
class Dictionary {
@@ -53,8 +55,8 @@ class Dictionary {
static const int KIND_FLAG_POSSIBLY_OFFENSIVE = 0x80000000;
static const int KIND_FLAG_EXACT_MATCH = 0x40000000;
- Dictionary(JNIEnv *env,
- DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPoilcy);
+ Dictionary(JNIEnv *env, const DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
+ &dictionaryStructureWithBufferPoilcy);
int getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
@@ -87,20 +89,22 @@ class Dictionary {
const int maxResultLength);
const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const {
- return mDictionaryStructureWithBufferPolicy;
+ return mDictionaryStructureWithBufferPolicy.get();
}
- virtual ~Dictionary();
-
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary);
+ typedef ExclusiveOwnershipPointer<BigramDictionary> BigramDictionaryPtr;
+ typedef ExclusiveOwnershipPointer<SuggestInterface> SuggestInterfacePtr;
+
static const int HEADER_ATTRIBUTE_BUFFER_SIZE;
- DictionaryStructureWithBufferPolicy *const mDictionaryStructureWithBufferPolicy;
- const BigramDictionary *const mBigramDictionary;
- const SuggestInterface *const mGestureSuggest;
- const SuggestInterface *const mTypingSuggest;
+ const DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
+ mDictionaryStructureWithBufferPolicy;
+ const BigramDictionaryPtr mBigramDictionary;
+ const SuggestInterfacePtr mGestureSuggest;
+ const SuggestInterfacePtr mTypingSuggest;
void logDictionaryInfo(JNIEnv *const env) const;
};
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.cpp b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
new file mode 100644
index 000000000..0635fef7e
--- /dev/null
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#include "suggest/core/dictionary/error_type_utils.h"
+
+namespace latinime {
+
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::NOT_AN_ERROR = 0x0;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_CASE_ERROR = 0x1;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR = 0x2;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_DIGRAPH = 0x4;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::INTENTIONAL_OMISSION = 0x8;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::EDIT_CORRECTION = 0x10;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::PROXIMITY_CORRECTION = 0x20;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::COMPLETION = 0x40;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::NEW_WORD = 0x80;
+
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::ERRORS_TREATED_AS_AN_EXACT_MATCH =
+ NOT_AN_ERROR | MATCH_WITH_CASE_ERROR | MATCH_WITH_ACCENT_ERROR | MATCH_WITH_DIGRAPH;
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.h b/native/jni/src/suggest/core/dictionary/error_type_utils.h
new file mode 100644
index 000000000..ab4a65e48
--- /dev/null
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_ERROR_TYPE_UTILS_H
+#define LATINIME_ERROR_TYPE_UTILS_H
+
+#include <stdint.h>
+
+#include "defines.h"
+
+namespace latinime {
+
+class ErrorTypeUtils {
+ public:
+ // ErrorType is mainly decided by CorrectionType but it is also depending on if
+ // the correction has really been performed or not.
+ typedef uint32_t ErrorType;
+
+ static const ErrorType NOT_AN_ERROR;
+ static const ErrorType MATCH_WITH_CASE_ERROR;
+ static const ErrorType MATCH_WITH_ACCENT_ERROR;
+ static const ErrorType MATCH_WITH_DIGRAPH;
+ // Treat error as an intentional omission when the CorrectionType is omission and the node can
+ // be intentional omission.
+ static const ErrorType INTENTIONAL_OMISSION;
+ // Substitution, omission and transposition
+ static const ErrorType EDIT_CORRECTION;
+ // Proximity error
+ static const ErrorType PROXIMITY_CORRECTION;
+ // Completion
+ static const ErrorType COMPLETION;
+ // New word
+ // TODO: Remove.
+ // A new word error should be an edit correction error or a proximity correction error.
+ static const ErrorType NEW_WORD;
+
+ // TODO: Differentiate errors.
+ static bool isExactMatch(const ErrorType containingErrors) {
+ return (containingErrors & ~ERRORS_TREATED_AS_AN_EXACT_MATCH) == 0;
+ }
+
+ static bool isEditCorrectionError(const ErrorType errorType) {
+ return (errorType & EDIT_CORRECTION) != 0;
+ }
+
+ static bool isProximityCorrectionError(const ErrorType errorType) {
+ return (errorType & PROXIMITY_CORRECTION) != 0;
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ErrorTypeUtils);
+
+ static const ErrorType ERRORS_TREATED_AS_AN_EXACT_MATCH;
+};
+} // namespace latinime
+#endif // LATINIME_ERROR_TYPE_UTILS_H
diff --git a/native/jni/src/suggest/core/layout/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp
index e64476d82..ee8e59ef9 100644
--- a/native/jni/src/suggest/core/layout/proximity_info.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info.cpp
@@ -71,7 +71,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr,
&& sweetSpotCenterYs && sweetSpotRadii),
mProximityCharsArray(new int[GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE
/* proximityCharsLength */]),
- mCodeToKeyMap() {
+ mLowerCodePointToKeyMap() {
/* Let's check the input array length here to make sure */
const jsize proximityCharsLength = env->GetArrayLength(proximityChars);
if (proximityCharsLength != GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE) {
@@ -147,7 +147,14 @@ int ProximityInfo::getCodePointOf(const int keyIndex) const {
if (keyIndex < 0 || keyIndex >= KEY_COUNT) {
return NOT_A_CODE_POINT;
}
- return mKeyIndexToCodePointG[keyIndex];
+ return mKeyIndexToLowerCodePointG[keyIndex];
+}
+
+int ProximityInfo::getOriginalCodePointOf(const int keyIndex) const {
+ if (keyIndex < 0 || keyIndex >= KEY_COUNT) {
+ return NOT_A_CODE_POINT;
+ }
+ return mKeyIndexToOriginalCodePoint[keyIndex];
}
void ProximityInfo::initializeG() {
@@ -164,8 +171,9 @@ void ProximityInfo::initializeG() {
const float gapY = sweetSpotCenterY - mCenterYsG[i];
mSweetSpotCenterYsG[i] = static_cast<int>(mCenterYsG[i] + gapY * verticalScale);
}
- mCodeToKeyMap[lowerCode] = i;
- mKeyIndexToCodePointG[i] = lowerCode;
+ mLowerCodePointToKeyMap[lowerCode] = i;
+ mKeyIndexToOriginalCodePoint[i] = code;
+ mKeyIndexToLowerCodePointG[i] = lowerCode;
}
for (int i = 0; i < KEY_COUNT; i++) {
mKeyKeyDistancesG[i][i] = 0;
diff --git a/native/jni/src/suggest/core/layout/proximity_info.h b/native/jni/src/suggest/core/layout/proximity_info.h
index f25949001..a91b9d674 100644
--- a/native/jni/src/suggest/core/layout/proximity_info.h
+++ b/native/jni/src/suggest/core/layout/proximity_info.h
@@ -39,6 +39,7 @@ class ProximityInfo {
float getNormalizedSquaredDistanceFromCenterFloatG(
const int keyId, const int x, const int y, const bool isGeometric) const;
int getCodePointOf(const int keyIndex) const;
+ int getOriginalCodePointOf(const int keyIndex) const;
bool hasSweetSpotData(const int keyIndex) const {
// When there are no calibration data for a key,
// the radius of the key is assigned to zero.
@@ -76,11 +77,11 @@ class ProximityInfo {
ProximityInfoUtils::initializeProximities(inputCodes, inputXCoordinates, inputYCoordinates,
inputSize, mKeyXCoordinates, mKeyYCoordinates, mKeyWidths, mKeyHeights,
mProximityCharsArray, CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH, MOST_COMMON_KEY_WIDTH,
- KEY_COUNT, mLocaleStr, &mCodeToKeyMap, allInputCodes);
+ KEY_COUNT, mLocaleStr, &mLowerCodePointToKeyMap, allInputCodes);
}
AK_FORCE_INLINE int getKeyIndexOf(const int c) const {
- return ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, c, &mCodeToKeyMap);
+ return ProximityInfoUtils::getKeyIndexOf(KEY_COUNT, c, &mLowerCodePointToKeyMap);
}
AK_FORCE_INLINE bool isCodePointOnKeyboard(const int codePoint) const {
@@ -117,9 +118,9 @@ class ProximityInfo {
// Sweet spots for geometric input. Note that we have extra sweet spots only for Y coordinates.
float mSweetSpotCenterYsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
- hash_map_compat<int, int> mCodeToKeyMap;
-
- int mKeyIndexToCodePointG[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ hash_map_compat<int, int> mLowerCodePointToKeyMap;
+ int mKeyIndexToOriginalCodePoint[MAX_KEY_COUNT_IN_A_KEYBOARD];
+ int mKeyIndexToLowerCodePointG[MAX_KEY_COUNT_IN_A_KEYBOARD];
int mCenterXsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
int mCenterYsG[MAX_KEY_COUNT_IN_A_KEYBOARD];
int mKeyKeyDistancesG[MAX_KEY_COUNT_IN_A_KEYBOARD][MAX_KEY_COUNT_IN_A_KEYBOARD];
diff --git a/native/jni/src/suggest/core/layout/proximity_info_state.cpp b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
index fbabd92f2..bb4b41714 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_state.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
@@ -30,6 +30,12 @@
namespace latinime {
+int ProximityInfoState::getPrimaryOriginalCodePointAt(const int index) const {
+ const int primaryCodePoint = getPrimaryCodePointAt(index);
+ const int keyIndex = mProximityInfo->getKeyIndexOf(primaryCodePoint);
+ return mProximityInfo->getOriginalCodePointOf(keyIndex);
+}
+
// TODO: Remove the dependency of "isGeometric"
void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
diff --git a/native/jni/src/suggest/core/layout/proximity_info_state.h b/native/jni/src/suggest/core/layout/proximity_info_state.h
index c94060fa9..e941e43d8 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_state.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.h
@@ -65,6 +65,8 @@ class ProximityInfoState {
return getProximityCodePointsAt(index)[0];
}
+ int getPrimaryOriginalCodePointAt(const int index) const;
+
inline bool sameAsTyped(const int *word, int length) const {
if (length != mSampledInputSize) {
return false;
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
index 41f82049f..e649844dc 100644
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
@@ -18,6 +18,7 @@
#define LATINIME_DICTIONARY_STRUCTURE_POLICY_H
#include "defines.h"
+#include "utils/exclusive_ownership_pointer.h"
namespace latinime {
@@ -33,18 +34,20 @@ class DictionaryShortcutsStructurePolicy;
*/
class DictionaryStructureWithBufferPolicy {
public:
+ typedef ExclusiveOwnershipPointer<DictionaryStructureWithBufferPolicy> StructurePoilcyPtr;
+
virtual ~DictionaryStructureWithBufferPolicy() {}
virtual int getRootPosition() const = 0;
- virtual void createAndGetAllChildNodes(const DicNode *const dicNode,
+ virtual void createAndGetAllChildDicNodes(const DicNode *const dicNode,
DicNodeVector *const childDicNodes) const = 0;
virtual int getCodePointsAndProbabilityAndReturnCodePointCount(
const int nodePos, const int maxCodePointCount, int *const outCodePoints,
int *const outUnigramProbability) const = 0;
- virtual int getTerminalNodePositionOfWord(const int *const inWord,
+ virtual int getTerminalPtNodePositionOfWord(const int *const inWord,
const int length, const bool forceLowerCaseSearch) const = 0;
virtual int getProbability(const int unigramProbability,
diff --git a/native/jni/src/suggest/core/policy/weighting.cpp b/native/jni/src/suggest/core/policy/weighting.cpp
index 0c4016893..c202b81fe 100644
--- a/native/jni/src/suggest/core/policy/weighting.cpp
+++ b/native/jni/src/suggest/core/policy/weighting.cpp
@@ -20,6 +20,7 @@
#include "suggest/core/dicnode/dic_node.h"
#include "suggest/core/dicnode/dic_node_profiler.h"
#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/dictionary/error_type_utils.h"
#include "suggest/core/session/dic_traverse_session.h"
namespace latinime {
@@ -82,8 +83,8 @@ static inline void profile(const CorrectionType correctionType, DicNode *const n
traverseSession, parentDicNode, dicNode, &inputStateG);
const float languageCost = Weighting::getLanguageCost(weighting, correctionType,
traverseSession, parentDicNode, dicNode, multiBigramMap);
- const ErrorType errorType = weighting->getErrorType(correctionType, traverseSession,
- parentDicNode, dicNode);
+ const ErrorTypeUtils::ErrorType errorType = weighting->getErrorType(correctionType,
+ traverseSession, parentDicNode, dicNode);
profile(correctionType, dicNode);
if (inputStateG.mNeedsToUpdateInputStateG) {
dicNode->updateInputIndexG(&inputStateG);
diff --git a/native/jni/src/suggest/core/policy/weighting.h b/native/jni/src/suggest/core/policy/weighting.h
index 2d49e98a6..bd6b3cf41 100644
--- a/native/jni/src/suggest/core/policy/weighting.h
+++ b/native/jni/src/suggest/core/policy/weighting.h
@@ -18,6 +18,7 @@
#define LATINIME_WEIGHTING_H
#include "defines.h"
+#include "suggest/core/dictionary/error_type_utils.h"
namespace latinime {
@@ -84,7 +85,7 @@ class Weighting {
virtual float getSpaceSubstitutionCost(const DicTraverseSession *const traverseSession,
const DicNode *const dicNode) const = 0;
- virtual ErrorType getErrorType(const CorrectionType correctionType,
+ virtual ErrorTypeUtils::ErrorType getErrorType(const CorrectionType correctionType,
const DicTraverseSession *const traverseSession,
const DicNode *const parentDicNode, const DicNode *const dicNode) const = 0;
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
index 50f2bbd8d..5070491f4 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -35,16 +35,16 @@ void DicTraverseSession::init(const Dictionary *const dictionary, const int *pre
->getMultiWordCostMultiplier();
mSuggestOptions = suggestOptions;
if (!prevWord) {
- mPrevWordPos = NOT_A_DICT_POS;
+ mPrevWordPtNodePos = NOT_A_DICT_POS;
return;
}
// TODO: merge following similar calls to getTerminalPosition into one case-insensitive call.
- mPrevWordPos = getDictionaryStructurePolicy()->getTerminalNodePositionOfWord(
+ mPrevWordPtNodePos = getDictionaryStructurePolicy()->getTerminalPtNodePositionOfWord(
prevWord, prevWordLength, false /* forceLowerCaseSearch */);
- if (mPrevWordPos == NOT_A_DICT_POS) {
+ if (mPrevWordPtNodePos == NOT_A_DICT_POS) {
// Check bigrams for lower-cased previous word if original was not found. Useful for
// auto-capitalized words like "The [current_word]".
- mPrevWordPos = getDictionaryStructurePolicy()->getTerminalNodePositionOfWord(
+ mPrevWordPtNodePos = getDictionaryStructurePolicy()->getTerminalPtNodePositionOfWord(
prevWord, prevWordLength, true /* forceLowerCaseSearch */);
}
}
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
index e0b1c67d9..6e4dda44d 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -59,7 +59,7 @@ class DicTraverseSession {
}
AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache)
- : mPrevWordPos(NOT_A_DICT_POS), mProximityInfo(0),
+ : mPrevWordPtNodePos(NOT_A_DICT_POS), mProximityInfo(0),
mDictionary(0), mSuggestOptions(0), mDicNodesCache(usesLargeCache),
mMultiBigramMap(), mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
mMultiWordCostMultiplier(1.0f) {
@@ -86,11 +86,9 @@ class DicTraverseSession {
//--------------------
const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
- int getPrevWordPos() const { return mPrevWordPos; }
+ int getPrevWordPtNodePos() const { return mPrevWordPtNodePos; }
// TODO: REMOVE
- void setPrevWordPos(int pos) { mPrevWordPos = pos; }
- // TODO: Use proper parameter when changed
- int getDicRootPos() const { return 0; }
+ void setPrevWordPtNodePos(const int ptNodePos) { mPrevWordPtNodePos = ptNodePos; }
DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; }
const ProximityInfoState *getProximityInfoState(int id) const {
@@ -119,26 +117,13 @@ class DicTraverseSession {
return true;
}
- void getSearchKeys(const DicNode *node, std::vector<int> *const outputSearchKeyVector) const {
- for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
- if (!mProximityInfoStates[i].isUsed()) {
- continue;
- }
- const int pointerId = node->getInputIndex(i);
- const std::vector<int> *const searchKeyVector =
- mProximityInfoStates[i].getSearchKeyVector(pointerId);
- outputSearchKeyVector->insert(outputSearchKeyVector->end(), searchKeyVector->begin(),
- searchKeyVector->end());
- }
- }
-
- ProximityType getProximityTypeG(const DicNode *const node, const int childCodePoint) const {
+ ProximityType getProximityTypeG(const DicNode *const dicNode, const int childCodePoint) const {
ProximityType proximityType = UNRELATED_CHAR;
for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
if (!mProximityInfoStates[i].isUsed()) {
continue;
}
- const int pointerId = node->getInputIndex(i);
+ const int pointerId = dicNode->getInputIndex(i);
proximityType = mProximityInfoStates[i].getProximityTypeG(pointerId, childCodePoint);
ASSERT(proximityType == UNRELATED_CHAR || proximityType == MATCH_CHAR);
// TODO: Make this more generic
@@ -192,7 +177,7 @@ class DicTraverseSession {
const int *const inputYs, const int *const times, const int *const pointerIds,
const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
- int mPrevWordPos;
+ int mPrevWordPtNodePos;
const ProximityInfo *mProximityInfo;
const Dictionary *mDictionary;
const SuggestOptions *mSuggestOptions;
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index 73ccebc88..2eda414f4 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -98,7 +98,7 @@ void Suggest::initializeSearch(DicTraverseSession *traverseSession, int commitPo
// Continue suggestion after partial commit.
DicNode *topDicNode =
traverseSession->getDicTraverseCache()->setCommitPoint(commitPoint);
- traverseSession->setPrevWordPos(topDicNode->getPrevWordNodePos());
+ traverseSession->setPrevWordPtNodePos(topDicNode->getPrevWordPtNodePos());
traverseSession->getDicTraverseCache()->continueSearch();
traverseSession->setPartiallyCommited();
}
@@ -109,7 +109,7 @@ void Suggest::initializeSearch(DicTraverseSession *traverseSession, int commitPo
// Create a new dic node here
DicNode rootNode;
DicNodeUtils::initAsRoot(traverseSession->getDictionaryStructurePolicy(),
- traverseSession->getPrevWordPos(), &rootNode);
+ traverseSession->getPrevWordPtNodePos(), &rootNode);
traverseSession->getDicTraverseCache()->copyPushActive(&rootNode);
}
}
@@ -231,7 +231,7 @@ int Suggest::outputSuggestions(DicTraverseSession *traverseSession, int *frequen
BinaryDictionaryShortcutIterator shortcutIt(
traverseSession->getDictionaryStructurePolicy()->getShortcutsStructurePolicy(),
traverseSession->getDictionaryStructurePolicy()
- ->getShortcutPositionOfPtNode(terminalDicNode->getPos()));
+ ->getShortcutPositionOfPtNode(terminalDicNode->getPtNodePos()));
// Shortcut is not supported for multiple words suggestions.
// TODO: Check shortcuts during traversal for multiple words suggestions.
const bool sameAsTyped = TRAVERSAL->sameAsTyped(traverseSession, terminalDicNode);
@@ -421,15 +421,15 @@ void Suggest::expandCurrentDicNodes(DicTraverseSession *traverseSession) const {
}
break;
case UNRELATED_CHAR:
- // Just drop this node and do nothing.
+ // Just drop this dicNode and do nothing.
break;
default:
- // Just drop this node and do nothing.
+ // Just drop this dicNode and do nothing.
break;
}
}
- // Push the node for look-ahead correction
+ // Push the dicNode for look-ahead correction
if (allowsErrorCorrections && canDoLookAheadCorrection) {
traverseSession->getDicTraverseCache()->copyPushNextActive(&dicNode);
}
@@ -442,7 +442,7 @@ void Suggest::processTerminalDicNode(
if (dicNode->getCompoundDistance() >= static_cast<float>(MAX_VALUE_FOR_WEIGHTING)) {
return;
}
- if (!dicNode->isTerminalWordNode()) {
+ if (!dicNode->isTerminalDicNode()) {
return;
}
if (dicNode->shouldBeFilteredBySafetyNetForBigram()) {
@@ -463,7 +463,7 @@ void Suggest::processTerminalDicNode(
/**
* Adds the expanded dicNode to the next search priority queue. Also creates an additional next word
- * (by the space omission error correction) search path if input dicNode is on a terminal node.
+ * (by the space omission error correction) search path if input dicNode is on a terminal.
*/
void Suggest::processExpandedDicNode(
DicTraverseSession *traverseSession, DicNode *dicNode) const {
@@ -505,7 +505,7 @@ void Suggest::processDicNodeAsSubstitution(DicTraverseSession *traverseSession,
processExpandedDicNode(traverseSession, childDicNode);
}
-// Process the node codepoint as a digraph. This means that composite glyphs like the German
+// Process the DicNode codepoint as a digraph. This means that composite glyphs like the German
// u-umlaut is expanded to the transliteration "ue". Note that this happens in parallel with
// the normal non-digraph traversal, so both "uber" and "ueber" can be corrected to "[u-umlaut]ber".
void Suggest::processDicNodeAsDigraph(DicTraverseSession *traverseSession,
@@ -518,7 +518,7 @@ void Suggest::processDicNodeAsDigraph(DicTraverseSession *traverseSession,
/**
* Handle the dicNode as an omission error (e.g., ths => this). Skip the current letter and consider
* matches for all possible next letters. Note that just skipping the current letter without any
- * other conditions tends to flood the search dic nodes cache with omission nodes. Instead, check
+ * other conditions tends to flood the search DicNodes cache with omission DicNodes. Instead, check
* the possible *next* letters after the omission to better limit search to plausible omissions.
* Note that apostrophes are handled as omissions.
*/
@@ -605,7 +605,7 @@ void Suggest::processDicNodeAsTransposition(DicTraverseSession *traverseSession,
}
/**
- * Weight child node by aligning it to the key
+ * Weight child dicNode by aligning it to the key
*/
void Suggest::weightChildNode(DicTraverseSession *traverseSession, DicNode *dicNode) const {
const int inputSize = traverseSession->getInputSize();
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp
index 1926b9831..de9fc9bbc 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.cpp
@@ -16,7 +16,7 @@
#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.cpp
index b1170e251..83a32fb0b 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.cpp
@@ -17,8 +17,8 @@
#include "suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h"
#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
@@ -157,8 +157,9 @@ bool DynamicBigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(
}
const int bigramTargetNodePos =
followBigramLinkAndGetCurrentBigramPtNodePos(originalBigramPos);
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(bigramTargetNodePos);
- if (nodeReader.isDeleted() || !nodeReader.isTerminal()
+ const PtNodeParams ptNodeParams(nodeReader.fetchNodeInfoInBufferFromPtNodePos(
+ bigramTargetNodePos));
+ if (ptNodeParams.isDeleted() || !ptNodeParams.isTerminal()
|| bigramTargetNodePos == NOT_A_DICT_POS) {
// The target is no longer valid terminal. Invalidate the current bigram entry.
if (!BigramListReadWriteUtils::writeBigramEntry(mBuffer, bigramFlags,
@@ -342,20 +343,22 @@ int DynamicBigramListPolicy::followBigramLinkAndGetCurrentBigramPtNodePos(
if (originalBigramPos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- int currentPos = originalBigramPos;
DynamicPatriciaTrieNodeReader nodeReader(mBuffer, this /* bigramsPolicy */, mShortcutPolicy);
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(currentPos);
+ int currentPos = NOT_A_DICT_POS;
int bigramLinkCount = 0;
- while (nodeReader.getBigramLinkedNodePos() != NOT_A_DICT_POS) {
- currentPos = nodeReader.getBigramLinkedNodePos();
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(currentPos);
+ int bigramLinkedNodePos = originalBigramPos;
+ do {
+ currentPos = bigramLinkedNodePos;
+ const PtNodeParams ptNodeParams(nodeReader.fetchNodeInfoInBufferFromPtNodePos(currentPos));
+ bigramLinkedNodePos = ptNodeParams.getBigramLinkedNodePos();
bigramLinkCount++;
if (bigramLinkCount > CONTINUING_BIGRAM_LINK_COUNT_LIMIT) {
AKLOGE("Bigram link is invalid. start position: %d", originalBigramPos);
ASSERT(false);
return NOT_A_DICT_POS;
}
- }
+ bigramLinkedNodePos = ptNodeParams.getBigramLinkedNodePos();
+ } while (bigramLinkedNodePos != NOT_A_DICT_POS);
return currentPos;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h
index 0504b59d5..5de456656 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h
@@ -22,7 +22,7 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h"
namespace latinime {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.cpp
deleted file mode 100644
index ff80dd2f6..000000000
--- a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.cpp
+++ /dev/null
@@ -1,53 +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.
- */
-
-#include "suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h"
-
-#include <stdint.h>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h"
-#include "suggest/policyimpl/dictionary/patricia_trie_policy.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-
-namespace latinime {
-
-/* static */ DictionaryStructureWithBufferPolicy *DictionaryStructureWithBufferPolicyFactory
- ::newDictionaryStructureWithBufferPolicy(const char *const path, const int bufOffset,
- const int size, const bool isUpdatable) {
- // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
- // impl classes of DictionaryStructureWithBufferPolicy.
- const MmappedBuffer *const mmapedBuffer = MmappedBuffer::openBuffer(path, bufOffset, size,
- isUpdatable);
- if (!mmapedBuffer) {
- return 0;
- }
- switch (FormatUtils::detectFormatVersion(mmapedBuffer->getBuffer(),
- mmapedBuffer->getBufferSize())) {
- case FormatUtils::VERSION_2:
- return new PatriciaTriePolicy(mmapedBuffer);
- case FormatUtils::VERSION_3:
- return new DynamicPatriciaTriePolicy(mmapedBuffer);
- default:
- AKLOGE("DICT: dictionary format is unknown, bad magic number");
- delete mmapedBuffer;
- ASSERT(false);
- return 0;
- }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
deleted file mode 100644
index 2fa3111d3..000000000
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
+++ /dev/null
@@ -1,124 +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.
- */
-
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
-
-#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-void DynamicPatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProcessMovedPtNode(
- const int ptNodePos, const int maxCodePointCount, int *const outCodePoints) {
- if (ptNodePos < 0 || ptNodePos >= mBuffer->getTailPosition()) {
- // Reading invalid position because of bug or broken dictionary.
- AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
- ptNodePos, mBuffer->getTailPosition());
- ASSERT(false);
- invalidatePtNodeInfo();
- return;
- }
- const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodePos);
- const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
- int pos = ptNodePos;
- mHeadPos = ptNodePos;
- if (usesAdditionalBuffer) {
- pos -= mBuffer->getOriginalBufferSize();
- }
- mFlags = PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
- const int parentPosOffset =
- DynamicPatriciaTrieReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(dictBuf,
- &pos);
- mParentPos = DynamicPatriciaTrieReadingUtils::getParentPtNodePos(parentPosOffset, mHeadPos);
- if (outCodePoints != 0) {
- mCodePointCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
- dictBuf, mFlags, maxCodePointCount, outCodePoints, &pos);
- } else {
- mCodePointCount = PatriciaTrieReadingUtils::skipCharacters(
- dictBuf, mFlags, MAX_WORD_LENGTH, &pos);
- }
- if (isTerminal()) {
- mProbabilityFieldPos = pos;
- if (usesAdditionalBuffer) {
- mProbabilityFieldPos += mBuffer->getOriginalBufferSize();
- }
- mProbability = PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(dictBuf, &pos);
- } else {
- mProbabilityFieldPos = NOT_A_DICT_POS;
- mProbability = NOT_A_PROBABILITY;
- }
- mChildrenPosFieldPos = pos;
- if (usesAdditionalBuffer) {
- mChildrenPosFieldPos += mBuffer->getOriginalBufferSize();
- }
- mChildrenPos = DynamicPatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
- dictBuf, &pos);
- if (usesAdditionalBuffer && mChildrenPos != NOT_A_DICT_POS) {
- mChildrenPos += mBuffer->getOriginalBufferSize();
- }
- if (mSiblingPos == NOT_A_DICT_POS) {
- if (DynamicPatriciaTrieReadingUtils::isMoved(mFlags)) {
- mBigramLinkedNodePos = mChildrenPos;
- } else {
- mBigramLinkedNodePos = NOT_A_DICT_POS;
- }
- }
- if (usesAdditionalBuffer) {
- pos += mBuffer->getOriginalBufferSize();
- }
- if (PatriciaTrieReadingUtils::hasShortcutTargets(mFlags)) {
- mShortcutPos = pos;
- mShortcutsPolicy->skipAllShortcuts(&pos);
- } else {
- mShortcutPos = NOT_A_DICT_POS;
- }
- if (PatriciaTrieReadingUtils::hasBigrams(mFlags)) {
- mBigramPos = pos;
- mBigramsPolicy->skipAllBigrams(&pos);
- } else {
- mBigramPos = NOT_A_DICT_POS;
- }
- // Update siblingPos if needed.
- if (mSiblingPos == NOT_A_DICT_POS) {
- // Sibling position is the tail position of current node.
- mSiblingPos = pos;
- }
- // Read destination node if the read node is a moved node.
- if (DynamicPatriciaTrieReadingUtils::isMoved(mFlags)) {
- // The destination position is stored at the same place as the parent position.
- fetchPtNodeInfoFromBufferAndProcessMovedPtNode(mParentPos, maxCodePointCount,
- outCodePoints);
- }
-}
-
-void DynamicPatriciaTrieNodeReader::invalidatePtNodeInfo() {
- mHeadPos = NOT_A_DICT_POS;
- mFlags = 0;
- mParentPos = NOT_A_DICT_POS;
- mCodePointCount = 0;
- mProbabilityFieldPos = NOT_A_DICT_POS;
- mProbability = NOT_A_PROBABILITY;
- mChildrenPosFieldPos = NOT_A_DICT_POS;
- mChildrenPos = NOT_A_DICT_POS;
- mBigramLinkedNodePos = NOT_A_DICT_POS;
- mShortcutPos = NOT_A_DICT_POS;
- mBigramPos = NOT_A_DICT_POS;
- mSiblingPos = NOT_A_DICT_POS;
-}
-
-}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h
deleted file mode 100644
index 3b36d425f..000000000
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h
+++ /dev/null
@@ -1,163 +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.
- */
-
-#ifndef LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H
-#define LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H
-
-#include <stdint.h>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-class DictionaryBigramsStructurePolicy;
-class DictionaryShortcutsStructurePolicy;
-
-/*
- * This class is used for helping to read nodes of dynamic patricia trie. This class handles moved
- * node and reads node attributes.
- */
-class DynamicPatriciaTrieNodeReader {
- public:
- DynamicPatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer,
- const DictionaryBigramsStructurePolicy *const bigramsPolicy,
- const DictionaryShortcutsStructurePolicy *const shortcutsPolicy)
- : mBuffer(buffer), mBigramsPolicy(bigramsPolicy),
- mShortcutsPolicy(shortcutsPolicy), mHeadPos(NOT_A_DICT_POS), mFlags(0),
- mParentPos(NOT_A_DICT_POS), mCodePointCount(0), mProbabilityFieldPos(NOT_A_DICT_POS),
- mProbability(NOT_A_PROBABILITY), mChildrenPosFieldPos(NOT_A_DICT_POS),
- mChildrenPos(NOT_A_DICT_POS), mBigramLinkedNodePos(NOT_A_DICT_POS),
- mShortcutPos(NOT_A_DICT_POS), mBigramPos(NOT_A_DICT_POS),
- mSiblingPos(NOT_A_DICT_POS) {}
-
- ~DynamicPatriciaTrieNodeReader() {}
-
- // Reads PtNode information from dictionary buffer and updates members with the information.
- AK_FORCE_INLINE void fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) {
- fetchNodeInfoInBufferFromPtNodePosAndGetNodeCodePoints(ptNodePos ,
- 0 /* maxCodePointCount */, 0 /* outCodePoints */);
- }
-
- AK_FORCE_INLINE void fetchNodeInfoInBufferFromPtNodePosAndGetNodeCodePoints(
- const int ptNodePos, const int maxCodePointCount, int *const outCodePoints) {
- mSiblingPos = NOT_A_DICT_POS;
- mBigramLinkedNodePos = NOT_A_DICT_POS;
- fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos, maxCodePointCount, outCodePoints);
- }
-
- // HeadPos is different from NodePos when the current PtNode is a moved PtNode.
- AK_FORCE_INLINE int getHeadPos() const {
- return mHeadPos;
- }
-
- // Flags
- AK_FORCE_INLINE bool isDeleted() const {
- return DynamicPatriciaTrieReadingUtils::isDeleted(mFlags);
- }
-
- AK_FORCE_INLINE bool hasChildren() const {
- return mChildrenPos != NOT_A_DICT_POS;
- }
-
- AK_FORCE_INLINE bool isTerminal() const {
- return PatriciaTrieReadingUtils::isTerminal(mFlags);
- }
-
- AK_FORCE_INLINE bool isBlacklisted() const {
- return PatriciaTrieReadingUtils::isBlacklisted(mFlags);
- }
-
- AK_FORCE_INLINE bool isNotAWord() const {
- return PatriciaTrieReadingUtils::isNotAWord(mFlags);
- }
-
- // Parent node position
- AK_FORCE_INLINE int getParentPos() const {
- return mParentPos;
- }
-
- // Number of code points
- AK_FORCE_INLINE uint8_t getCodePointCount() const {
- return mCodePointCount;
- }
-
- // Probability
- AK_FORCE_INLINE int getProbabilityFieldPos() const {
- return mProbabilityFieldPos;
- }
-
- AK_FORCE_INLINE int getProbability() const {
- return mProbability;
- }
-
- // Children PtNode array position
- AK_FORCE_INLINE int getChildrenPosFieldPos() const {
- return mChildrenPosFieldPos;
- }
-
- AK_FORCE_INLINE int getChildrenPos() const {
- return mChildrenPos;
- }
-
- // Bigram linked node position.
- AK_FORCE_INLINE int getBigramLinkedNodePos() const {
- return mBigramLinkedNodePos;
- }
-
- // Shortcutlist position
- AK_FORCE_INLINE int getShortcutPos() const {
- return mShortcutPos;
- }
-
- // Bigrams position
- AK_FORCE_INLINE int getBigramsPos() const {
- return mBigramPos;
- }
-
- // Sibling node position
- AK_FORCE_INLINE int getSiblingNodePos() const {
- return mSiblingPos;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DynamicPatriciaTrieNodeReader);
-
- const BufferWithExtendableBuffer *const mBuffer;
- const DictionaryBigramsStructurePolicy *const mBigramsPolicy;
- const DictionaryShortcutsStructurePolicy *const mShortcutsPolicy;
- int mHeadPos;
- DynamicPatriciaTrieReadingUtils::NodeFlags mFlags;
- int mParentPos;
- uint8_t mCodePointCount;
- int mProbabilityFieldPos;
- int mProbability;
- int mChildrenPosFieldPos;
- int mChildrenPos;
- int mBigramLinkedNodePos;
- int mShortcutPos;
- int mBigramPos;
- int mSiblingPos;
-
- void fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
- const int maxCodePointCount, int *const outCodePoints);
-
- void invalidatePtNodeInfo();
-};
-} // namespace latinime
-#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H */
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 a9c7805a8..7c06a7117 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
@@ -30,8 +30,8 @@ namespace latinime {
class HeaderPolicy : public DictionaryHeaderStructurePolicy {
public:
// Reads information from existing dictionary buffer.
- HeaderPolicy(const uint8_t *const dictBuf, const int dictSize)
- : mDictFormatVersion(FormatUtils::detectFormatVersion(dictBuf, dictSize)),
+ HeaderPolicy(const uint8_t *const dictBuf, const FormatUtils::FORMAT_VERSION formatVersion)
+ : mDictFormatVersion(formatVersion),
mDictionaryFlags(HeaderReadWriteUtils::getFlags(dictBuf)),
mSize(HeaderReadWriteUtils::getHeaderSize(dictBuf)),
mAttributeMap(createAttributeMapAndReadAllAttributes(dictBuf)),
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 5ded8f6a1..5ef8e50b4 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
@@ -118,6 +118,9 @@ const char *const HeaderReadWriteUtils::REQUIRES_FRENCH_LIGATURE_PROCESSING_KEY
case FormatUtils::VERSION_3:
return buffer->writeUintAndAdvancePosition(3 /* data */,
HEADER_DICTIONARY_VERSION_SIZE, writingPos);
+ case FormatUtils::VERSION_4:
+ return buffer->writeUintAndAdvancePosition(4 /* data */,
+ HEADER_DICTIONARY_VERSION_SIZE, writingPos);
default:
return false;
}
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
new file mode 100644
index 000000000..3ab6a8e21
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
+
+#include <stdint.h>
+#include <string>
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h"
+#include "suggest/policyimpl/dictionary/utils/format_utils.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+
+/* static */ DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
+ DictionaryStructureWithBufferPolicyFactory
+ ::newDictionaryStructureWithBufferPolicy(const char *const path,
+ const int bufOffset, const int size, const bool isUpdatable) {
+ // Allocated buffer in MmapedBuffer::newBuffer() will be freed in the destructor of
+ // MmappedBufferWrapper if the instance has the responsibility.
+ MmappedBuffer::MmappedBufferPtr mmappedBuffer(MmappedBuffer::openBuffer(path, bufOffset, size,
+ isUpdatable));
+ if (!mmappedBuffer.get()) {
+ return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(0);
+ }
+ switch (FormatUtils::detectFormatVersion(mmappedBuffer.get()->getBuffer(),
+ mmappedBuffer.get()->getBufferSize())) {
+ case FormatUtils::VERSION_2:
+ return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(
+ new PatriciaTriePolicy(mmappedBuffer));
+ case FormatUtils::VERSION_3:
+ return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(
+ new DynamicPatriciaTriePolicy(mmappedBuffer));
+ case FormatUtils::VERSION_4: {
+ std::string dictDirPath(path);
+ const std::string::size_type pos =
+ dictDirPath.rfind(Ver4DictConstants::TRIE_FILE_EXTENSION);
+ if (pos == std::string::npos) {
+ // Dictionary file name is not valid as a version 4 dictionary.
+ return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(0);
+ }
+ // Removing extension to get the base path.
+ dictDirPath.erase(pos);
+ const Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
+ Ver4DictBuffers::openVer4DictBuffers(dictDirPath.c_str(), mmappedBuffer));
+ if (!dictBuffers.get()->isValid()) {
+ AKLOGE("DICT: The dictionary doesn't satisfy ver4 format requirements.");
+ ASSERT(false);
+ return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(0);
+ }
+ return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(
+ new Ver4PatriciaTriePolicy(dictBuffers));
+ }
+ default:
+ AKLOGE("DICT: dictionary format is unknown, bad magic number");
+ ASSERT(false);
+ return DictionaryStructureWithBufferPolicy::StructurePoilcyPtr(0);
+ }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
index 8cebc3b16..1359575f1 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dictionary_structure_with_buffer_policy_factory.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
@@ -21,13 +21,15 @@
#include "defines.h"
#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "utils/exclusive_ownership_pointer.h"
namespace latinime {
class DictionaryStructureWithBufferPolicyFactory {
public:
- static DictionaryStructureWithBufferPolicy *newDictionaryStructureWithBufferPolicy(
- const char *const path, const int bufOffset, const int size, const bool isUpdatable);
+ static DictionaryStructureWithBufferPolicy::StructurePoilcyPtr
+ newDictionaryStructureWithBufferPolicy(const char *const path, const int bufOffset,
+ const int size, const bool isUpdatable);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);
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
new file mode 100644
index 000000000..7bdd829cd
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PT_NODE_PARAMS_H
+#define LATINIME_PT_NODE_PARAMS_H
+
+#include <cstring>
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+
+// This class has information of a PtNode. This class is immutable.
+class PtNodeParams {
+ public:
+ // Invalid PtNode.
+ PtNodeParams() : mHeadPos(NOT_A_DICT_POS), mFlags(0), mParentPos(NOT_A_DICT_POS),
+ mCodePointCount(0), mCodePoints(), mTerminalIdFieldPos(NOT_A_DICT_POS),
+ mTerminalId(Ver4DictConstants::NOT_A_TERMINAL), mProbabilityFieldPos(NOT_A_DICT_POS),
+ mProbability(NOT_A_PROBABILITY), mChildrenPosFieldPos(NOT_A_DICT_POS),
+ mChildrenPos(NOT_A_DICT_POS), mBigramLinkedNodePos(NOT_A_DICT_POS),
+ mShortcutPos(NOT_A_DICT_POS), mBigramPos(NOT_A_DICT_POS),
+ mSiblingPos(NOT_A_DICT_POS) {}
+
+ PtNodeParams(const PtNodeParams& ptNodeParams)
+ : mHeadPos(ptNodeParams.mHeadPos), mFlags(ptNodeParams.mFlags),
+ mParentPos(ptNodeParams.mParentPos), mCodePointCount(ptNodeParams.mCodePointCount),
+ mCodePoints(), mTerminalIdFieldPos(ptNodeParams.mTerminalIdFieldPos),
+ mTerminalId(ptNodeParams.mTerminalId),
+ mProbabilityFieldPos(ptNodeParams.mProbabilityFieldPos),
+ mProbability(ptNodeParams.mProbability),
+ mChildrenPosFieldPos(ptNodeParams.mChildrenPosFieldPos),
+ mChildrenPos(ptNodeParams.mChildrenPos),
+ mBigramLinkedNodePos(ptNodeParams.mBigramLinkedNodePos),
+ mShortcutPos(ptNodeParams.mShortcutPos), mBigramPos(ptNodeParams.mBigramPos),
+ mSiblingPos(ptNodeParams.mSiblingPos) {
+ memcpy(mCodePoints, ptNodeParams.getCodePoints(), sizeof(int) * mCodePointCount);
+ }
+
+ PtNodeParams(const int headPos, const PatriciaTrieReadingUtils::NodeFlags flags,
+ const int parentPos, const int codePointCount, const int *const codePoints,
+ const int probabilityFieldPos, const int probability, const int childrenPosFieldPos,
+ const int childrenPos, const int bigramLinkedNodePos, const int shortcutPos,
+ const int bigramPos, const int siblingPos)
+ : mHeadPos(headPos), mFlags(flags), mParentPos(parentPos),
+ mCodePointCount(codePointCount), mCodePoints(),
+ mTerminalIdFieldPos(NOT_A_DICT_POS), mTerminalId(Ver4DictConstants::NOT_A_TERMINAL),
+ mProbabilityFieldPos(probabilityFieldPos), mProbability(probability),
+ mChildrenPosFieldPos(childrenPosFieldPos), mChildrenPos(childrenPos),
+ mBigramLinkedNodePos(bigramLinkedNodePos), mShortcutPos(shortcutPos),
+ mBigramPos(bigramPos), mSiblingPos(siblingPos) {
+ memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
+ }
+
+ AK_FORCE_INLINE bool isValid() const {
+ return mCodePointCount > 0;
+ }
+
+ // Head position of the PtNode
+ AK_FORCE_INLINE int getHeadPos() const {
+ return mHeadPos;
+ }
+
+ // Flags
+ AK_FORCE_INLINE bool isDeleted() const {
+ return DynamicPatriciaTrieReadingUtils::isDeleted(mFlags);
+ }
+
+ AK_FORCE_INLINE bool hasChildren() const {
+ return mChildrenPos != NOT_A_DICT_POS;
+ }
+
+ AK_FORCE_INLINE bool isTerminal() const {
+ return PatriciaTrieReadingUtils::isTerminal(mFlags);
+ }
+
+ AK_FORCE_INLINE bool isBlacklisted() const {
+ return PatriciaTrieReadingUtils::isBlacklisted(mFlags);
+ }
+
+ AK_FORCE_INLINE bool isNotAWord() const {
+ return PatriciaTrieReadingUtils::isNotAWord(mFlags);
+ }
+
+ // Parent node position
+ AK_FORCE_INLINE int getParentPos() const {
+ return mParentPos;
+ }
+
+ // Number of code points
+ AK_FORCE_INLINE uint8_t getCodePointCount() const {
+ return mCodePointCount;
+ }
+
+ AK_FORCE_INLINE const int *getCodePoints() const {
+ return mCodePoints;
+ }
+
+ // Probability
+ AK_FORCE_INLINE int getTerminalIdFieldPos() const {
+ return mTerminalIdFieldPos;
+ }
+
+ AK_FORCE_INLINE int getTerminalId() const {
+ return mTerminalId;
+ }
+
+ // Probability
+ AK_FORCE_INLINE int getProbabilityFieldPos() const {
+ return mProbabilityFieldPos;
+ }
+
+ AK_FORCE_INLINE int getProbability() const {
+ return mProbability;
+ }
+
+ // Children PtNode array position
+ AK_FORCE_INLINE int getChildrenPosFieldPos() const {
+ return mChildrenPosFieldPos;
+ }
+
+ AK_FORCE_INLINE int getChildrenPos() const {
+ return mChildrenPos;
+ }
+
+ // Bigram linked node position.
+ AK_FORCE_INLINE int getBigramLinkedNodePos() const {
+ return mBigramLinkedNodePos;
+ }
+
+ // Shortcutlist position
+ AK_FORCE_INLINE int getShortcutPos() const {
+ return mShortcutPos;
+ }
+
+ // Bigrams position
+ AK_FORCE_INLINE int getBigramsPos() const {
+ return mBigramPos;
+ }
+
+ // Sibling node position
+ AK_FORCE_INLINE int getSiblingNodePos() const {
+ return mSiblingPos;
+ }
+
+ private:
+ // This class have a public copy constructor to be used as a return value.
+
+ // Disallowing the assignment operator.
+ PtNodeParams &operator=(PtNodeParams &ptNodeParams);
+
+ const int mHeadPos;
+ const PatriciaTrieReadingUtils::NodeFlags mFlags;
+ const int mParentPos;
+ const uint8_t mCodePointCount;
+ int mCodePoints[MAX_WORD_LENGTH];
+ const int mTerminalIdFieldPos;
+ const int mTerminalId;
+ const int mProbabilityFieldPos;
+ const int mProbability;
+ const int mChildrenPosFieldPos;
+ const int mChildrenPos;
+ const int mBigramLinkedNodePos;
+ const int mShortcutPos;
+ const int mBigramPos;
+ const int mSiblingPos;
+};
+} // namespace latinime
+#endif /* LATINIME_PT_NODE_PARAMS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h
new file mode 100644
index 000000000..c6b2a8bed
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PT_NODE_READER_H
+#define LATINIME_PT_NODE_READER_H
+
+#include "defines.h"
+
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
+
+namespace latinime {
+
+// Interface class used to read PtNode information.
+class PtNodeReader {
+ public:
+ virtual ~PtNodeReader() {}
+ virtual const PtNodeParams fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) const = 0;
+
+ protected:
+ PtNodeReader() {};
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PtNodeReader);
+};
+} // namespace latinime
+#endif /* LATINIME_PT_NODE_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index 8a84bd261..960c1b936 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -15,22 +15,22 @@
*/
-#include "suggest/policyimpl/dictionary/patricia_trie_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h"
#include "defines.h"
#include "suggest/core/dicnode/dic_node.h"
#include "suggest/core/dicnode/dic_node_vector.h"
-#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h"
#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
namespace latinime {
-void PatriciaTriePolicy::createAndGetAllChildNodes(const DicNode *const dicNode,
+void PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
DicNodeVector *const childDicNodes) const {
if (!dicNode->hasChildren()) {
return;
}
- int nextPos = dicNode->getChildrenPos();
+ int nextPos = dicNode->getChildrenPtNodeArrayPos();
if (nextPos < 0 || nextPos >= mDictBufferSize) {
AKLOGE("Children PtNode array position is invalid. pos: %d, dict size: %d",
nextPos, mDictBufferSize);
@@ -52,14 +52,14 @@ void PatriciaTriePolicy::createAndGetAllChildNodes(const DicNode *const dicNode,
// This retrieves code points and the probability of the word by its terminal position.
// Due to the fact that words are ordered in the dictionary in a strict breadth-first order,
-// it is possible to check for this with advantageous complexity. For each node, we search
+// it is possible to check for this with advantageous complexity. For each PtNode array, we search
// for PtNodes with children and compare the children position with the position we look for.
// When we shoot the position we look for, it means the word we look for is in the children
// of the previous PtNode. The only tricky part is the fact that if we arrive at the end of a
// PtNode array with the last PtNode's children position still less than what we are searching for,
// we must descend the last PtNode's children (for example, if the word we are searching for starts
// with a z, it's the last PtNode of the root array, so all children addresses will be smaller
-// than the position we look for, and we have to descend the z node).
+// than the position we look for, and we have to descend the z PtNode).
/* Parameters :
* ptNodePos: the byte position of the terminal PtNode of the word we are searching for (this is
* what is stored as the "bigram position" in each bigram)
@@ -74,9 +74,9 @@ int PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
int pos = getRootPosition();
int wordPos = 0;
// One iteration of the outer loop iterates through PtNode arrays. As stated above, we will
- // only traverse nodes that are actually a part of the terminal we are searching, so each time
- // we enter this loop we are one depth level further than last time.
- // The only reason we count nodes is because we want to reduce the probability of infinite
+ // only traverse PtNodes that are actually a part of the terminal we are searching, so each
+ // time we enter this loop we are one depth level further than last time.
+ // The only reason we count PtNodes is because we want to reduce the probability of infinite
// looping in case there is a bug. Since we know there is an upper bound to the depth we are
// supposed to traverse, it does not hurt to count iterations.
for (int loopCount = maxCodePointCount; loopCount > 0; --loopCount) {
@@ -140,8 +140,9 @@ int PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
found = true;
} else if (1 >= ptNodeCount) {
// However if we are on the LAST PtNode of this array, and we have NOT shot the
- // position we should descend THIS node. So we trick the lastCandidatePtNodePos
- // so that we will descend this PtNode, not the previous one.
+ // position we should descend THIS PtNode. So we trick the
+ // lastCandidatePtNodePos so that we will descend this PtNode, not the previous
+ // one.
lastCandidatePtNodePos = startPos;
found = true;
} else {
@@ -149,7 +150,7 @@ int PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
found = false;
}
} else {
- // Even if we don't have children here, we could still be on the last PtNode of /
+ // Even if we don't have children here, we could still be on the last PtNode of
// this array. If this is the case, we should descend the last PtNode that had
// children, and their position is already in lastCandidatePtNodePos.
found = (1 >= ptNodeCount);
@@ -230,9 +231,9 @@ int PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
return 0;
}
-// This function gets the position of the terminal node of the exact matching word in the
+// This function gets the position of the terminal PtNode of the exact matching word in the
// dictionary. If no match is found, it returns NOT_A_DICT_POS.
-int PatriciaTriePolicy::getTerminalNodePositionOfWord(const int *const inWord,
+int PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
const int length, const bool forceLowerCaseSearch) const {
int pos = getRootPosition();
int wordPos = 0;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
index 0f8662aea..5d99632a5 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
@@ -24,6 +24,7 @@
#include "suggest/policyimpl/dictionary/bigram/bigram_list_policy.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h"
+#include "suggest/policyimpl/dictionary/utils/format_utils.h"
#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
namespace latinime {
@@ -33,28 +34,26 @@ class DicNodeVector;
class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
public:
- PatriciaTriePolicy(const MmappedBuffer *const buffer)
- : mBuffer(buffer), mHeaderPolicy(mBuffer->getBuffer(), buffer->getBufferSize()),
- mDictRoot(mBuffer->getBuffer() + mHeaderPolicy.getSize()),
- mDictBufferSize(mBuffer->getBufferSize() - mHeaderPolicy.getSize()),
+ PatriciaTriePolicy(const MmappedBuffer::MmappedBufferPtr &mmappedBuffer)
+ : mMmappedBuffer(mmappedBuffer),
+ mHeaderPolicy(mMmappedBuffer.get()->getBuffer(), FormatUtils::VERSION_2),
+ mDictRoot(mMmappedBuffer.get()->getBuffer() + mHeaderPolicy.getSize()),
+ mDictBufferSize(mMmappedBuffer.get()->getBufferSize()
+ - mHeaderPolicy.getSize()),
mBigramListPolicy(mDictRoot), mShortcutListPolicy(mDictRoot) {}
- ~PatriciaTriePolicy() {
- delete mBuffer;
- }
-
AK_FORCE_INLINE int getRootPosition() const {
return 0;
}
- void createAndGetAllChildNodes(const DicNode *const dicNode,
+ void createAndGetAllChildDicNodes(const DicNode *const dicNode,
DicNodeVector *const childDicNodes) const;
int getCodePointsAndProbabilityAndReturnCodePointCount(
const int terminalNodePos, const int maxCodePointCount, int *const outCodePoints,
int *const outUnigramProbability) const;
- int getTerminalNodePositionOfWord(const int *const inWord,
+ int getTerminalPtNodePositionOfWord(const int *const inWord,
const int length, const bool forceLowerCaseSearch) const;
int getProbability(const int unigramProbability, const int bigramProbability) const;
@@ -124,7 +123,7 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);
- const MmappedBuffer *const mBuffer;
+ const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
const HeaderPolicy mHeaderPolicy;
const uint8_t *const mDictRoot;
const int mDictBufferSize;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.cpp
index 7df55815f..82b3593c8 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_reading_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h"
#include "defines.h"
#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
diff --git a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h
index 8420ee95a..8420ee95a 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/patricia_trie_reading_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.cpp
index 5724c5d88..db4e86da1 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.cpp
@@ -14,25 +14,25 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.h"
#include "suggest/core/policy/dictionary_header_structure_policy.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
namespace latinime {
bool DynamicPatriciaTrieGcEventListeners
::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
- ::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints) {
+ ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
// PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
// children.
- bool isUselessPtNode = !node->isTerminal();
- if (node->isTerminal() && mIsDecayingDict) {
+ bool isUselessPtNode = !ptNodeParams->isTerminal();
+ if (ptNodeParams->isTerminal() && mIsDecayingDict) {
const int newProbability =
- ForgettingCurveUtils::getEncodedProbabilityToSave(node->getProbability(),
+ ForgettingCurveUtils::getEncodedProbabilityToSave(ptNodeParams->getProbability(),
mHeaderPolicy);
- int writingPos = node->getProbabilityFieldPos();
+ int writingPos = ptNodeParams->getProbabilityFieldPos();
// Update probability.
if (!DynamicPatriciaTrieWritingUtils::writeProbabilityAndAdvancePosition(
mBuffer, newProbability, &writingPos)) {
@@ -44,9 +44,9 @@ bool DynamicPatriciaTrieGcEventListeners
}
if (mChildrenValue > 0) {
isUselessPtNode = false;
- } else if (node->isTerminal()) {
+ } else if (ptNodeParams->isTerminal()) {
// Remove children as all children are useless.
- int writingPos = node->getChildrenPosFieldPos();
+ int writingPos = ptNodeParams->getChildrenPosFieldPos();
if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(
mBuffer, NOT_A_DICT_POS /* childrenPosition */, &writingPos)) {
return false;
@@ -54,12 +54,12 @@ bool DynamicPatriciaTrieGcEventListeners
}
if (isUselessPtNode) {
// Current PtNode is no longer needed. Mark it as deleted.
- if (!mWritingHelper->markNodeAsDeleted(node)) {
+ if (!mWritingHelper->markNodeAsDeleted(ptNodeParams)) {
return false;
}
} else {
mValueStack.back() += 1;
- if (node->isTerminal()) {
+ if (ptNodeParams->isTerminal()) {
mValidUnigramCount += 1;
}
}
@@ -67,10 +67,9 @@ bool DynamicPatriciaTrieGcEventListeners
}
bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateBigramProbability
- ::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints) {
- if (!node->isDeleted()) {
- int pos = node->getBigramsPos();
+ ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+ if (!ptNodeParams->isDeleted()) {
+ int pos = ptNodeParams->getBigramsPos();
if (pos != NOT_A_DICT_POS) {
int bigramEntryCount = 0;
if (!mBigramPolicy->updateAllBigramEntriesAndDeleteUselessEntries(&pos,
@@ -117,31 +116,29 @@ bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNo
// Write valid PtNode to buffer and memorize mapping from the old position to the new position.
bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
- ::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints) {
- if (node->isDeleted()) {
+ ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+ if (ptNodeParams->isDeleted()) {
// Current PtNode is not written in new buffer because it has been deleted.
mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap::value_type(
- node->getHeadPos(), NOT_A_DICT_POS));
+ ptNodeParams->getHeadPos(), NOT_A_DICT_POS));
return true;
}
int writingPos = mBufferToWrite->getTailPosition();
mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap::value_type(
- node->getHeadPos(), writingPos));
+ ptNodeParams->getHeadPos(), writingPos));
mValidPtNodeCount++;
// Writes current PtNode.
- return mWritingHelper->writePtNodeToBufferByCopyingPtNodeInfo(mBufferToWrite, node,
- node->getParentPos(), nodeCodePoints, node->getCodePointCount(),
- node->getProbability(), &writingPos);
+ return mWritingHelper->writePtNodeToBufferByCopyingPtNodeInfo(mBufferToWrite, ptNodeParams,
+ ptNodeParams->getParentPos(), ptNodeParams->getCodePoints(),
+ ptNodeParams->getCodePointCount(), ptNodeParams->getProbability(), &writingPos);
}
bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionFields
- ::onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints) {
+ ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
// Updates parent position.
- int parentPos = node->getParentPos();
+ int parentPos = ptNodeParams->getParentPos();
if (parentPos != NOT_A_DICT_POS) {
DynamicPatriciaTrieWritingHelper::PtNodePositionRelocationMap::const_iterator it =
mDictPositionRelocationMap->mPtNodePositionRelocationMap.find(parentPos);
@@ -149,15 +146,16 @@ bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionField
parentPos = it->second;
}
}
- int writingPos = node->getHeadPos() + DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE;
+ int writingPos = ptNodeParams->getHeadPos()
+ + DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE;
// Write updated parent offset.
if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition(mBufferToWrite,
- parentPos, node->getHeadPos(), &writingPos)) {
+ parentPos, ptNodeParams->getHeadPos(), &writingPos)) {
return false;
}
// Updates children position.
- int childrenPos = node->getChildrenPos();
+ int childrenPos = ptNodeParams->getChildrenPos();
if (childrenPos != NOT_A_DICT_POS) {
DynamicPatriciaTrieWritingHelper::PtNodeArrayPositionRelocationMap::const_iterator it =
mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.find(childrenPos);
@@ -165,14 +163,14 @@ bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionField
childrenPos = it->second;
}
}
- writingPos = node->getChildrenPosFieldPos();
+ writingPos = ptNodeParams->getChildrenPosFieldPos();
if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBufferToWrite,
childrenPos, &writingPos)) {
return false;
}
// Updates bigram target PtNode positions in the bigram list.
- int bigramsPos = node->getBigramsPos();
+ int bigramsPos = ptNodeParams->getBigramsPos();
if (bigramsPos != NOT_A_DICT_POS) {
int bigramEntryCount;
if (!mBigramPolicy->updateAllBigramTargetPtNodePositions(&bigramsPos,
@@ -181,7 +179,7 @@ bool DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionField
}
mBigramCount += bigramEntryCount;
}
- if (node->isTerminal()) {
+ if (ptNodeParams->isTerminal()) {
mUnigramCount++;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.h
index 9755120b0..cfe3c145c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.h
@@ -21,15 +21,16 @@
#include "defines.h"
#include "suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
#include "utils/hash_map_compat.h"
namespace latinime {
class DictionaryHeaderStructurePolicy;
+class PtNodeParams;
class DynamicPatriciaTrieGcEventListeners {
public:
@@ -66,8 +67,7 @@ class DynamicPatriciaTrieGcEventListeners {
bool onReadingPtNodeArrayTail() { return true; }
- bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints);
+ bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
int getValidUnigramCount() const {
return mValidUnigramCount;
@@ -101,8 +101,7 @@ class DynamicPatriciaTrieGcEventListeners {
bool onReadingPtNodeArrayTail() { return true; }
- bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints);
+ bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
int getValidBigramEntryCount() const {
return mValidBigramEntryCount;
@@ -133,8 +132,7 @@ class DynamicPatriciaTrieGcEventListeners {
bool onReadingPtNodeArrayTail();
- bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints);
+ bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToPlaceAndWriteValidPtNodesToBuffer);
@@ -167,8 +165,7 @@ class DynamicPatriciaTrieGcEventListeners {
bool onReadingPtNodeArrayTail() { return true; }
- bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints);
+ bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
int getUnigramCount() const {
return mUnigramCount;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.cpp
new file mode 100644
index 000000000..3393ce662
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h"
+
+#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
+#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+const PtNodeParams DynamicPatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProcessMovedPtNode(
+ const int ptNodePos, const int siblingNodePos, const int bigramLinkedNodePos) const {
+ if (ptNodePos < 0 || ptNodePos >= mBuffer->getTailPosition()) {
+ // Reading invalid position because of bug or broken dictionary.
+ AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
+ ptNodePos, mBuffer->getTailPosition());
+ ASSERT(false);
+ return PtNodeParams();
+ }
+ const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodePos);
+ const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+ int pos = ptNodePos;
+ const int headPos = ptNodePos;
+ if (usesAdditionalBuffer) {
+ pos -= mBuffer->getOriginalBufferSize();
+ }
+ const PatriciaTrieReadingUtils::NodeFlags flags =
+ PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+ const int parentPosOffset =
+ DynamicPatriciaTrieReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(dictBuf,
+ &pos);
+ const int parentPos =
+ DynamicPatriciaTrieReadingUtils::getParentPtNodePos(parentPosOffset, headPos);
+ int codePoints[MAX_WORD_LENGTH];
+ const int codePonitCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
+ dictBuf, flags, MAX_WORD_LENGTH, codePoints, &pos);
+ int probability = NOT_A_PROBABILITY;
+ int probabilityFieldPos = NOT_A_DICT_POS;
+ if (PatriciaTrieReadingUtils::isTerminal(flags)) {
+ probabilityFieldPos = pos;
+ if (usesAdditionalBuffer) {
+ probabilityFieldPos += mBuffer->getOriginalBufferSize();
+ }
+ probability = PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(dictBuf, &pos);
+ }
+ int childrenPosFieldPos = pos;
+ if (usesAdditionalBuffer) {
+ childrenPosFieldPos += mBuffer->getOriginalBufferSize();
+ }
+ int childrenPos = DynamicPatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
+ dictBuf, &pos);
+ if (usesAdditionalBuffer && childrenPos != NOT_A_DICT_POS) {
+ childrenPos += mBuffer->getOriginalBufferSize();
+ }
+ int newBigramLinkedNodePos = bigramLinkedNodePos;
+ if (siblingNodePos == NOT_A_DICT_POS) {
+ if (DynamicPatriciaTrieReadingUtils::isMoved(flags)) {
+ newBigramLinkedNodePos = childrenPos;
+ }
+ }
+ if (usesAdditionalBuffer) {
+ pos += mBuffer->getOriginalBufferSize();
+ }
+ int shortcutsPos = NOT_A_DICT_POS;
+ if (PatriciaTrieReadingUtils::hasShortcutTargets(flags)) {
+ shortcutsPos = pos;
+ mShortcutsPolicy->skipAllShortcuts(&pos);
+ }
+ int bigramsPos = NOT_A_DICT_POS;
+ if (PatriciaTrieReadingUtils::hasBigrams(flags)) {
+ bigramsPos = pos;
+ mBigramsPolicy->skipAllBigrams(&pos);
+ }
+ int newSiblingNodePos = siblingNodePos;
+ if (siblingNodePos == NOT_A_DICT_POS) {
+ // Sibling position is the tail position of current node.
+ newSiblingNodePos = pos;
+ }
+ // Read destination node if the read node is a moved node.
+ if (DynamicPatriciaTrieReadingUtils::isMoved(flags)) {
+ // The destination position is stored at the same place as the parent position.
+ return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(parentPos, newSiblingNodePos,
+ newBigramLinkedNodePos);
+ } else {
+ return PtNodeParams(headPos, flags, parentPos, codePonitCount, codePoints,
+ probabilityFieldPos, probability, childrenPosFieldPos, childrenPos,
+ newBigramLinkedNodePos, shortcutsPos, bigramsPos, newSiblingNodePos);
+ }
+}
+
+}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h
new file mode 100644
index 000000000..b5abffeda
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H
+#define LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H
+
+#include <stdint.h>
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+class DictionaryBigramsStructurePolicy;
+class DictionaryShortcutsStructurePolicy;
+
+/*
+ * This class is used for helping to read nodes of dynamic patricia trie. This class handles moved
+ * node and reads node attributes.
+ */
+class DynamicPatriciaTrieNodeReader : public PtNodeReader {
+ public:
+ DynamicPatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer,
+ const DictionaryBigramsStructurePolicy *const bigramsPolicy,
+ const DictionaryShortcutsStructurePolicy *const shortcutsPolicy)
+ : mBuffer(buffer), mBigramsPolicy(bigramsPolicy),
+ mShortcutsPolicy(shortcutsPolicy) {}
+
+ ~DynamicPatriciaTrieNodeReader() {}
+
+ virtual const PtNodeParams fetchNodeInfoInBufferFromPtNodePos(const int ptNodePos) const {
+ return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
+ NOT_A_DICT_POS /* siblingNodePos */, NOT_A_DICT_POS /* bigramLinkedNodePos */);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DynamicPatriciaTrieNodeReader);
+
+ const BufferWithExtendableBuffer *const mBuffer;
+ const DictionaryBigramsStructurePolicy *const mBigramsPolicy;
+ const DictionaryShortcutsStructurePolicy *const mShortcutsPolicy;
+
+ const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
+ const int siblingNodePos, const int bigramLinkedNodePos) const;
+};
+} // namespace latinime
+#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.cpp
index 495b146c2..50882b3e9 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.h"
#include <cstdio>
#include <cstring>
@@ -23,11 +23,11 @@
#include "defines.h"
#include "suggest/core/dicnode/dic_node.h"
#include "suggest/core/dicnode/dic_node_vector.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
-#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h"
#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
@@ -45,29 +45,32 @@ const int DynamicPatriciaTriePolicy::MAX_DICT_EXTENDED_REGION_SIZE = 1024 * 1024
const int DynamicPatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS =
DynamicPatriciaTrieWritingHelper::MAX_DICTIONARY_SIZE - 1024;
-void DynamicPatriciaTriePolicy::createAndGetAllChildNodes(const DicNode *const dicNode,
+void DynamicPatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
DicNodeVector *const childDicNodes) const {
if (!dicNode->hasChildren()) {
return;
}
- DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer,
- getBigramsStructurePolicy(), getShortcutsStructurePolicy());
- readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPos());
- const DynamicPatriciaTrieNodeReader *const nodeReader = readingHelper.getNodeReader();
+ DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer, &mNodeReader);
+ readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPtNodeArrayPos());
while (!readingHelper.isEnd()) {
- bool isTerminal = nodeReader->isTerminal() && !nodeReader->isDeleted();
+ const PtNodeParams ptNodeParams(readingHelper.getPtNodeParams());
+ if (!ptNodeParams.isValid()) {
+ break;
+ }
+ bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
if (isTerminal && mHeaderPolicy.isDecayingDict()) {
// A DecayingDict may have a terminal PtNode that has a terminal DicNode whose
// probability is NOT_A_PROBABILITY. In such case, we don't want to treat it as a
// valid terminal DicNode.
- isTerminal = getProbability(nodeReader->getProbability(), NOT_A_PROBABILITY)
+ isTerminal = getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY)
!= NOT_A_PROBABILITY;
}
- childDicNodes->pushLeavingChild(dicNode, nodeReader->getHeadPos(),
- nodeReader->getChildrenPos(), nodeReader->getProbability(), isTerminal,
- nodeReader->hasChildren(), nodeReader->isBlacklisted() || nodeReader->isNotAWord(),
- nodeReader->getCodePointCount(), readingHelper.getMergedNodeCodePoints());
- readingHelper.readNextSiblingNode();
+ childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
+ ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
+ ptNodeParams.hasChildren(),
+ ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord(),
+ ptNodeParams.getCodePointCount(), ptNodeParams.getCodePoints());
+ readingHelper.readNextSiblingNode(ptNodeParams);
}
}
@@ -77,29 +80,33 @@ int DynamicPatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCoun
// This method traverses parent nodes from the terminal by following parent pointers; thus,
// node code points are stored in the buffer in the reverse order.
int reverseCodePoints[maxCodePointCount];
- DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer,
- getBigramsStructurePolicy(), getShortcutsStructurePolicy());
+ DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer, &mNodeReader);
// First, read the terminal node and get its probability.
readingHelper.initWithPtNodePos(ptNodePos);
- if (!readingHelper.isValidTerminalNode()) {
+
+ const PtNodeParams terminalPtNodeParams(readingHelper.getPtNodeParams());
+ if (!readingHelper.isValidTerminalNode(terminalPtNodeParams)) {
// Node at the ptNodePos is not a valid terminal node.
*outUnigramProbability = NOT_A_PROBABILITY;
return 0;
}
// Store terminal node probability.
- *outUnigramProbability = readingHelper.getNodeReader()->getProbability();
+ *outUnigramProbability = terminalPtNodeParams.getProbability();
// Then, following parent node link to the dictionary root and fetch node code points.
+ int totalCodePointCount = 0;
while (!readingHelper.isEnd()) {
- if (readingHelper.getTotalCodePointCount() > maxCodePointCount) {
+ const PtNodeParams ptNodeParams(readingHelper.getPtNodeParams());
+ totalCodePointCount = readingHelper.getTotalCodePointCount(ptNodeParams);
+ if (!ptNodeParams.isValid() || totalCodePointCount > maxCodePointCount) {
// The ptNodePos is not a valid terminal node position in the dictionary.
*outUnigramProbability = NOT_A_PROBABILITY;
return 0;
}
// Store node code points to buffer in the reverse order.
- readingHelper.fetchMergedNodeCodePointsInReverseOrder(
+ readingHelper.fetchMergedNodeCodePointsInReverseOrder(ptNodeParams,
readingHelper.getPrevTotalCodePointCount(), reverseCodePoints);
// Follow parent node toward the root node.
- readingHelper.readParentNode();
+ readingHelper.readParentNode(ptNodeParams);
}
if (readingHelper.isError()) {
// The node position or the dictionary is invalid.
@@ -107,52 +114,54 @@ int DynamicPatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCoun
return 0;
}
// Reverse the stored code points to output them.
- const int codePointCount = readingHelper.getTotalCodePointCount();
- for (int i = 0; i < codePointCount; ++i) {
- outCodePoints[i] = reverseCodePoints[codePointCount - i - 1];
+ for (int i = 0; i < totalCodePointCount; ++i) {
+ outCodePoints[i] = reverseCodePoints[totalCodePointCount - i - 1];
}
- return codePointCount;
+ return totalCodePointCount;
}
-int DynamicPatriciaTriePolicy::getTerminalNodePositionOfWord(const int *const inWord,
+int DynamicPatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
const int length, const bool forceLowerCaseSearch) const {
int searchCodePoints[length];
for (int i = 0; i < length; ++i) {
searchCodePoints[i] = forceLowerCaseSearch ? CharUtils::toLowerCase(inWord[i]) : inWord[i];
}
- DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer,
- getBigramsStructurePolicy(), getShortcutsStructurePolicy());
+
+ DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer, &mNodeReader);
readingHelper.initWithPtNodeArrayPos(getRootPosition());
- const DynamicPatriciaTrieNodeReader *const nodeReader = readingHelper.getNodeReader();
while (!readingHelper.isEnd()) {
+ const PtNodeParams ptNodeParams(readingHelper.getPtNodeParams());
+ if (!ptNodeParams.isValid()) {
+ break;
+ }
const int matchedCodePointCount = readingHelper.getPrevTotalCodePointCount();
- if (readingHelper.getTotalCodePointCount() > length
- || !readingHelper.isMatchedCodePoint(0 /* index */,
+ if (readingHelper.getTotalCodePointCount(ptNodeParams) > length
+ || !readingHelper.isMatchedCodePoint(ptNodeParams, 0 /* index */,
searchCodePoints[matchedCodePointCount])) {
// Current node has too many code points or its first code point is different from
// target code point. Skip this node and read the next sibling node.
- readingHelper.readNextSiblingNode();
+ readingHelper.readNextSiblingNode(ptNodeParams);
continue;
}
// Check following merged node code points.
- const int nodeCodePointCount = nodeReader->getCodePointCount();
+ const int nodeCodePointCount = ptNodeParams.getCodePointCount();
for (int j = 1; j < nodeCodePointCount; ++j) {
- if (!readingHelper.isMatchedCodePoint(
+ if (!readingHelper.isMatchedCodePoint(ptNodeParams,
j, searchCodePoints[matchedCodePointCount + j])) {
// Different code point is found. The given word is not included in the dictionary.
return NOT_A_DICT_POS;
}
}
// All characters are matched.
- if (length == readingHelper.getTotalCodePointCount()) {
+ if (length == readingHelper.getTotalCodePointCount(ptNodeParams)) {
// Terminal position is found.
- return nodeReader->getHeadPos();
+ return ptNodeParams.getHeadPos();
}
- if (!nodeReader->hasChildren()) {
+ if (!ptNodeParams.hasChildren()) {
return NOT_A_DICT_POS;
}
// Advance to the children nodes.
- readingHelper.readChildNode();
+ readingHelper.readChildNode(ptNodeParams);
}
// If we already traversed the tree further than the word is long, there means
// there was no match (or we would have found it).
@@ -179,44 +188,38 @@ int DynamicPatriciaTriePolicy::getUnigramProbabilityOfPtNode(const int ptNodePos
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_PROBABILITY;
}
- DynamicPatriciaTrieNodeReader nodeReader(&mBufferWithExtendableBuffer,
- getBigramsStructurePolicy(), getShortcutsStructurePolicy());
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
- if (nodeReader.isDeleted() || nodeReader.isBlacklisted() || nodeReader.isNotAWord()) {
+ const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
return NOT_A_PROBABILITY;
}
- return getProbability(nodeReader.getProbability(), NOT_A_PROBABILITY);
+ return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
}
int DynamicPatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- DynamicPatriciaTrieNodeReader nodeReader(&mBufferWithExtendableBuffer,
- getBigramsStructurePolicy(), getShortcutsStructurePolicy());
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
- if (nodeReader.isDeleted()) {
+ const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ if (ptNodeParams.isDeleted()) {
return NOT_A_DICT_POS;
}
- return nodeReader.getShortcutPos();
+ return ptNodeParams.getShortcutPos();
}
int DynamicPatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
if (ptNodePos == NOT_A_DICT_POS) {
return NOT_A_DICT_POS;
}
- DynamicPatriciaTrieNodeReader nodeReader(&mBufferWithExtendableBuffer,
- getBigramsStructurePolicy(), getShortcutsStructurePolicy());
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos);
- if (nodeReader.isDeleted()) {
+ const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos));
+ if (ptNodeParams.isDeleted()) {
return NOT_A_DICT_POS;
}
- return nodeReader.getBigramsPos();
+ return ptNodeParams.getBigramsPos();
}
bool DynamicPatriciaTriePolicy::addUnigramWord(const int *const word, const int length,
const int probability) {
- if (!mBuffer->isUpdatable()) {
+ if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: addUnigramWord() is called for non-updatable dictionary.");
return false;
}
@@ -225,8 +228,7 @@ bool DynamicPatriciaTriePolicy::addUnigramWord(const int *const word, const int
AKLOGE("The dictionary is too large to dynamically update.");
return false;
}
- DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer,
- getBigramsStructurePolicy(), getShortcutsStructurePolicy());
+ DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer, &mNodeReader);
readingHelper.initWithPtNodeArrayPos(getRootPosition());
DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer,
&mBigramListPolicy, &mShortcutListPolicy, mHeaderPolicy.isDecayingDict());
@@ -244,7 +246,7 @@ bool DynamicPatriciaTriePolicy::addUnigramWord(const int *const word, const int
bool DynamicPatriciaTriePolicy::addBigramWords(const int *const word0, const int length0,
const int *const word1, const int length1, const int probability) {
- if (!mBuffer->isUpdatable()) {
+ if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary.");
return false;
}
@@ -253,12 +255,12 @@ bool DynamicPatriciaTriePolicy::addBigramWords(const int *const word0, const int
AKLOGE("The dictionary is too large to dynamically update.");
return false;
}
- const int word0Pos = getTerminalNodePositionOfWord(word0, length0,
+ const int word0Pos = getTerminalPtNodePositionOfWord(word0, length0,
false /* forceLowerCaseSearch */);
if (word0Pos == NOT_A_DICT_POS) {
return false;
}
- const int word1Pos = getTerminalNodePositionOfWord(word1, length1,
+ const int word1Pos = getTerminalPtNodePositionOfWord(word1, length1,
false /* forceLowerCaseSearch */);
if (word1Pos == NOT_A_DICT_POS) {
return false;
@@ -278,7 +280,7 @@ bool DynamicPatriciaTriePolicy::addBigramWords(const int *const word0, const int
bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const int length0,
const int *const word1, const int length1) {
- if (!mBuffer->isUpdatable()) {
+ if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: removeBigramWords() is called for non-updatable dictionary.");
return false;
}
@@ -287,12 +289,12 @@ bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const
AKLOGE("The dictionary is too large to dynamically update.");
return false;
}
- const int word0Pos = getTerminalNodePositionOfWord(word0, length0,
+ const int word0Pos = getTerminalPtNodePositionOfWord(word0, length0,
false /* forceLowerCaseSearch */);
if (word0Pos == NOT_A_DICT_POS) {
return false;
}
- const int word1Pos = getTerminalNodePositionOfWord(word1, length1,
+ const int word1Pos = getTerminalPtNodePositionOfWord(word1, length1,
false /* forceLowerCaseSearch */);
if (word1Pos == NOT_A_DICT_POS) {
return false;
@@ -308,7 +310,7 @@ bool DynamicPatriciaTriePolicy::removeBigramWords(const int *const word0, const
}
void DynamicPatriciaTriePolicy::flush(const char *const filePath) {
- if (!mBuffer->isUpdatable()) {
+ if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: flush() is called for non-updatable dictionary.");
return;
}
@@ -318,7 +320,7 @@ void DynamicPatriciaTriePolicy::flush(const char *const filePath) {
}
void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) {
- if (!mBuffer->isUpdatable()) {
+ if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
return;
}
@@ -334,7 +336,7 @@ void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) {
}
bool DynamicPatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
- if (!mBuffer->isUpdatable()) {
+ if (!mMmappedBuffer.get()->isUpdatable()) {
AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
return false;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.h
index be97ee1a5..7a81a9c0a 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_policy.h
@@ -22,7 +22,9 @@
#include "suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
#include "suggest/policyimpl/dictionary/shortcut/dynamic_shortcut_list_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/format_utils.h"
#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
namespace latinime {
@@ -32,32 +34,33 @@ class DicNodeVector;
class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
public:
- DynamicPatriciaTriePolicy(const MmappedBuffer *const buffer)
- : mBuffer(buffer), mHeaderPolicy(mBuffer->getBuffer(), buffer->getBufferSize()),
- mBufferWithExtendableBuffer(mBuffer->getBuffer() + mHeaderPolicy.getSize(),
- mBuffer->getBufferSize() - mHeaderPolicy.getSize()),
+ DynamicPatriciaTriePolicy(const MmappedBuffer::MmappedBufferPtr &mmappedBuffer)
+ : mMmappedBuffer(mmappedBuffer),
+ mHeaderPolicy(mMmappedBuffer.get()->getBuffer(), FormatUtils::VERSION_3),
+ mBufferWithExtendableBuffer(mMmappedBuffer.get()->getBuffer()
+ + mHeaderPolicy.getSize(), mMmappedBuffer.get()->getBufferSize()
+ - mHeaderPolicy.getSize(),
+ BufferWithExtendableBuffer
+ ::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
mShortcutListPolicy(&mBufferWithExtendableBuffer),
mBigramListPolicy(&mHeaderPolicy, &mBufferWithExtendableBuffer, &mShortcutListPolicy,
mHeaderPolicy.isDecayingDict()),
+ mNodeReader(&mBufferWithExtendableBuffer, &mBigramListPolicy, &mShortcutListPolicy),
mUnigramCount(mHeaderPolicy.getUnigramCount()),
mBigramCount(mHeaderPolicy.getBigramCount()), mNeedsToDecayForTesting(false) {}
- ~DynamicPatriciaTriePolicy() {
- delete mBuffer;
- }
-
AK_FORCE_INLINE int getRootPosition() const {
return 0;
}
- void createAndGetAllChildNodes(const DicNode *const dicNode,
+ void createAndGetAllChildDicNodes(const DicNode *const dicNode,
DicNodeVector *const childDicNodes) const;
int getCodePointsAndProbabilityAndReturnCodePointCount(
const int terminalPtNodePos, const int maxCodePointCount, int *const outCodePoints,
int *const outUnigramProbability) const;
- int getTerminalNodePositionOfWord(const int *const inWord,
+ int getTerminalPtNodePositionOfWord(const int *const inWord,
const int length, const bool forceLowerCaseSearch) const;
int getProbability(const int unigramProbability, const int bigramProbability) const;
@@ -108,11 +111,12 @@ class DynamicPatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
static const int MAX_DICT_EXTENDED_REGION_SIZE;
static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS;
- const MmappedBuffer *const mBuffer;
+ const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
const HeaderPolicy mHeaderPolicy;
BufferWithExtendableBuffer mBufferWithExtendableBuffer;
DynamicShortcutListPolicy mShortcutListPolicy;
DynamicBigramListPolicy mBigramListPolicy;
+ DynamicPatriciaTrieNodeReader mNodeReader;
int mUnigramCount;
int mBigramCount;
int mNeedsToDecayForTesting;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.cpp
index f108c219f..398ff21cf 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.cpp
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
namespace latinime {
// To avoid infinite loop caused by invalid or malicious forward links.
const int DynamicPatriciaTrieReadingHelper::MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP = 100000;
-const int DynamicPatriciaTrieReadingHelper::MAX_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP = 100000;
+const int DynamicPatriciaTrieReadingHelper::MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP = 100000;
const size_t DynamicPatriciaTrieReadingHelper::MAX_READING_STATE_STACK_SIZE = MAX_WORD_LENGTH;
// Visits all PtNodes in post-order depth first manner.
@@ -37,22 +39,26 @@ bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPostorderDepthFirstMa
return false;
}
while (!isEnd()) {
+ const PtNodeParams ptNodeParams(getPtNodeParams());
+ if (!ptNodeParams.isValid()) {
+ break;
+ }
if (!alreadyVisitedChildren) {
- if (mNodeReader.hasChildren()) {
+ if (ptNodeParams.hasChildren()) {
// Move to the first child.
- if (!listener->onDescend(mNodeReader.getChildrenPos())) {
+ if (!listener->onDescend(ptNodeParams.getChildrenPos())) {
return false;
}
pushReadingStateToStack();
- readChildNode();
+ readChildNode(ptNodeParams);
} else {
alreadyVisitedChildren = true;
}
} else {
- if (!listener->onVisitingPtNode(&mNodeReader, mMergedNodeCodePoints)) {
+ if (!listener->onVisitingPtNode(&ptNodeParams)) {
return false;
}
- readNextSiblingNode();
+ readNextSiblingNode(ptNodeParams);
if (isEnd()) {
// All PtNodes in current linked PtNode arrays have been visited.
// Return to the parent.
@@ -101,10 +107,14 @@ bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreor
}
pushReadingStateToStack();
while (!isEnd()) {
+ const PtNodeParams ptNodeParams(getPtNodeParams());
+ if (!ptNodeParams.isValid()) {
+ break;
+ }
if (alreadyVisitedAllPtNodesInArray) {
if (alreadyVisitedChildren) {
// Move to next sibling PtNode's children.
- readNextSiblingNode();
+ readNextSiblingNode(ptNodeParams);
if (isEnd()) {
// Return to the parent PTNode.
if (!listener->onAscend()) {
@@ -120,13 +130,13 @@ bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreor
alreadyVisitedChildren = false;
}
} else {
- if (mNodeReader.hasChildren()) {
+ if (ptNodeParams.hasChildren()) {
// Move to the first child.
- if (!listener->onDescend(mNodeReader.getChildrenPos())) {
+ if (!listener->onDescend(ptNodeParams.getChildrenPos())) {
return false;
}
pushReadingStateToStack();
- readChildNode();
+ readChildNode(ptNodeParams);
// Push state to return the head of PtNode array.
pushReadingStateToStack();
alreadyVisitedAllPtNodesInArray = false;
@@ -136,10 +146,10 @@ bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreor
}
}
} else {
- if (!listener->onVisitingPtNode(&mNodeReader, mMergedNodeCodePoints)) {
+ if (!listener->onVisitingPtNode(&ptNodeParams)) {
return false;
}
- readNextSiblingNode();
+ readNextSiblingNode(ptNodeParams);
if (isEnd()) {
if (!listener->onReadingPtNodeArrayTail()) {
return false;
@@ -170,35 +180,41 @@ void DynamicPatriciaTrieReadingHelper::nextPtNodeArray() {
mReadingState.mPos = NOT_A_DICT_POS;
return;
}
- mReadingState.mPosOfLastPtNodeArrayHead = mReadingState.mPos;
+ mReadingState.mPosOfThisPtNodeArrayHead = mReadingState.mPos;
const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(mReadingState.mPos);
const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
if (usesAdditionalBuffer) {
mReadingState.mPos -= mBuffer->getOriginalBufferSize();
}
- mReadingState.mNodeCount = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
- dictBuf, &mReadingState.mPos);
+ mReadingState.mRemainingPtNodeCountInThisArray =
+ PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(dictBuf,
+ &mReadingState.mPos);
if (usesAdditionalBuffer) {
mReadingState.mPos += mBuffer->getOriginalBufferSize();
}
// Count up nodes and node arrays to avoid infinite loop.
- mReadingState.mTotalNodeCount += mReadingState.mNodeCount;
- mReadingState.mNodeArrayCount++;
- if (mReadingState.mNodeCount < 0
- || mReadingState.mTotalNodeCount > MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP
- || mReadingState.mNodeArrayCount > MAX_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP) {
+ mReadingState.mTotalPtNodeIndexInThisArrayChain +=
+ mReadingState.mRemainingPtNodeCountInThisArray;
+ mReadingState.mPtNodeArrayIndexInThisArrayChain++;
+ if (mReadingState.mRemainingPtNodeCountInThisArray < 0
+ || mReadingState.mTotalPtNodeIndexInThisArrayChain
+ > MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP
+ || mReadingState.mPtNodeArrayIndexInThisArrayChain
+ > MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP) {
// Invalid dictionary.
AKLOGI("Invalid dictionary. nodeCount: %d, totalNodeCount: %d, MAX_CHILD_COUNT: %d"
"nodeArrayCount: %d, MAX_NODE_ARRAY_COUNT: %d",
- mReadingState.mNodeCount, mReadingState.mTotalNodeCount,
- MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP, mReadingState.mNodeArrayCount,
- MAX_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP);
+ mReadingState.mRemainingPtNodeCountInThisArray,
+ mReadingState.mTotalPtNodeIndexInThisArrayChain,
+ MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP,
+ mReadingState.mPtNodeArrayIndexInThisArrayChain,
+ MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP);
ASSERT(false);
mIsError = true;
mReadingState.mPos = NOT_A_DICT_POS;
return;
}
- if (mReadingState.mNodeCount == 0) {
+ if (mReadingState.mRemainingPtNodeCountInThisArray == 0) {
// Empty node array. Try following forward link.
followForwardLink();
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h
index a71c06971..1e9218e58 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h
@@ -21,9 +21,8 @@
#include <vector>
#include "defines.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
+#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
namespace latinime {
@@ -35,6 +34,7 @@ class DictionaryShortcutsStructurePolicy;
* This class is used for traversing dynamic patricia trie. This class supports iterating nodes and
* dealing with additional buffer. This class counts nodes and node arrays to avoid infinite loop.
*/
+// TODO: Move to pt_common.
class DynamicPatriciaTrieReadingHelper {
public:
class TraversingEventListener {
@@ -51,8 +51,7 @@ class DynamicPatriciaTrieReadingHelper {
virtual bool onReadingPtNodeArrayTail() = 0;
// Returns whether the event handling was succeeded or not.
- virtual bool onVisitingPtNode(const DynamicPatriciaTrieNodeReader *const node,
- const int *const nodeCodePoints) = 0;
+ virtual bool onVisitingPtNode(const PtNodeParams *const node) = 0;
protected:
TraversingEventListener() {};
@@ -62,10 +61,9 @@ class DynamicPatriciaTrieReadingHelper {
};
DynamicPatriciaTrieReadingHelper(const BufferWithExtendableBuffer *const buffer,
- const DictionaryBigramsStructurePolicy *const bigramsPolicy,
- const DictionaryShortcutsStructurePolicy *const shortcutsPolicy)
+ const PtNodeReader *const ptNodeReader)
: mIsError(false), mReadingState(), mBuffer(buffer),
- mNodeReader(mBuffer, bigramsPolicy, shortcutsPolicy), mReadingStateStack() {}
+ mPtNodeReader(ptNodeReader), mReadingStateStack() {}
~DynamicPatriciaTrieReadingHelper() {}
@@ -84,15 +82,12 @@ class DynamicPatriciaTrieReadingHelper {
} else {
mIsError = false;
mReadingState.mPos = ptNodeArrayPos;
- mReadingState.mPrevTotalCodePointCount = 0;
- mReadingState.mTotalNodeCount = 0;
- mReadingState.mNodeArrayCount = 0;
+ mReadingState.mTotalCodePointCountSinceInitialization = 0;
+ mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
+ mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
mReadingStateStack.clear();
nextPtNodeArray();
- if (!isEnd()) {
- fetchPtNodeInfo();
- }
}
}
@@ -103,94 +98,88 @@ class DynamicPatriciaTrieReadingHelper {
} else {
mIsError = false;
mReadingState.mPos = ptNodePos;
- mReadingState.mNodeCount = 1;
- mReadingState.mPrevTotalCodePointCount = 0;
- mReadingState.mTotalNodeCount = 1;
- mReadingState.mNodeArrayCount = 1;
+ mReadingState.mRemainingPtNodeCountInThisArray = 1;
+ mReadingState.mTotalCodePointCountSinceInitialization = 0;
+ mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
+ mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
- mReadingState.mPosOfLastPtNodeArrayHead = NOT_A_DICT_POS;
+ mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
mReadingStateStack.clear();
- fetchPtNodeInfo();
}
}
- AK_FORCE_INLINE const DynamicPatriciaTrieNodeReader* getNodeReader() const {
- return &mNodeReader;
+ AK_FORCE_INLINE const PtNodeParams getPtNodeParams() const {
+ if (isEnd()) {
+ return PtNodeParams();
+ }
+ return mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(mReadingState.mPos);
}
- AK_FORCE_INLINE bool isValidTerminalNode() const {
- return !isEnd() && !mNodeReader.isDeleted() && mNodeReader.isTerminal();
+ AK_FORCE_INLINE bool isValidTerminalNode(const PtNodeParams &ptNodeParams) const {
+ return !isEnd() && !ptNodeParams.isDeleted() && ptNodeParams.isTerminal();
}
- AK_FORCE_INLINE bool isMatchedCodePoint(const int index, const int codePoint) const {
- return mMergedNodeCodePoints[index] == codePoint;
+ AK_FORCE_INLINE bool isMatchedCodePoint(const PtNodeParams &ptNodeParams, const int index,
+ const int codePoint) const {
+ return ptNodeParams.getCodePoints()[index] == codePoint;
}
// Return code point count exclude the last read node's code points.
AK_FORCE_INLINE int getPrevTotalCodePointCount() const {
- return mReadingState.mPrevTotalCodePointCount;
+ return mReadingState.mTotalCodePointCountSinceInitialization;
}
// Return code point count include the last read node's code points.
- AK_FORCE_INLINE int getTotalCodePointCount() const {
- return mReadingState.mPrevTotalCodePointCount + mNodeReader.getCodePointCount();
+ AK_FORCE_INLINE int getTotalCodePointCount(const PtNodeParams &ptNodeParams) const {
+ return mReadingState.mTotalCodePointCountSinceInitialization
+ + ptNodeParams.getCodePointCount();
}
- AK_FORCE_INLINE void fetchMergedNodeCodePointsInReverseOrder(
+ AK_FORCE_INLINE void fetchMergedNodeCodePointsInReverseOrder(const PtNodeParams &ptNodeParams,
const int index, int *const outCodePoints) const {
- const int nodeCodePointCount = mNodeReader.getCodePointCount();
+ const int nodeCodePointCount = ptNodeParams.getCodePointCount();
+ const int *const nodeCodePoints = ptNodeParams.getCodePoints();
for (int i = 0; i < nodeCodePointCount; ++i) {
- outCodePoints[index + i] = mMergedNodeCodePoints[nodeCodePointCount - 1 - i];
+ outCodePoints[index + i] = nodeCodePoints[nodeCodePointCount - 1 - i];
}
}
- AK_FORCE_INLINE const int *getMergedNodeCodePoints() const {
- return mMergedNodeCodePoints;
- }
-
- AK_FORCE_INLINE void readNextSiblingNode() {
- mReadingState.mNodeCount -= 1;
- mReadingState.mPos = mNodeReader.getSiblingNodePos();
- if (mReadingState.mNodeCount <= 0) {
+ AK_FORCE_INLINE void readNextSiblingNode(const PtNodeParams &ptNodeParams) {
+ mReadingState.mRemainingPtNodeCountInThisArray -= 1;
+ mReadingState.mPos = ptNodeParams.getSiblingNodePos();
+ if (mReadingState.mRemainingPtNodeCountInThisArray <= 0) {
// All nodes in the current node array have been read.
followForwardLink();
- if (!isEnd()) {
- fetchPtNodeInfo();
- }
- } else {
- fetchPtNodeInfo();
}
}
// Read the first child node of the current node.
- AK_FORCE_INLINE void readChildNode() {
- if (mNodeReader.hasChildren()) {
- mReadingState.mPrevTotalCodePointCount += mNodeReader.getCodePointCount();
- mReadingState.mTotalNodeCount = 0;
- mReadingState.mNodeArrayCount = 0;
- mReadingState.mPos = mNodeReader.getChildrenPos();
+ AK_FORCE_INLINE void readChildNode(const PtNodeParams &ptNodeParams) {
+ if (ptNodeParams.hasChildren()) {
+ mReadingState.mTotalCodePointCountSinceInitialization +=
+ ptNodeParams.getCodePointCount();
+ mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
+ mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
+ mReadingState.mPos = ptNodeParams.getChildrenPos();
mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
// Read children node array.
nextPtNodeArray();
- if (!isEnd()) {
- fetchPtNodeInfo();
- }
} else {
mReadingState.mPos = NOT_A_DICT_POS;
}
}
// Read the parent node of the current node.
- AK_FORCE_INLINE void readParentNode() {
- if (mNodeReader.getParentPos() != NOT_A_DICT_POS) {
- mReadingState.mPrevTotalCodePointCount += mNodeReader.getCodePointCount();
- mReadingState.mTotalNodeCount = 1;
- mReadingState.mNodeArrayCount = 1;
- mReadingState.mNodeCount = 1;
- mReadingState.mPos = mNodeReader.getParentPos();
+ AK_FORCE_INLINE void readParentNode(const PtNodeParams &ptNodeParams) {
+ if (ptNodeParams.getParentPos() != NOT_A_DICT_POS) {
+ mReadingState.mTotalCodePointCountSinceInitialization +=
+ ptNodeParams.getCodePointCount();
+ mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
+ mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
+ mReadingState.mRemainingPtNodeCountInThisArray = 1;
+ mReadingState.mPos = ptNodeParams.getParentPos();
mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
- mReadingState.mPosOfLastPtNodeArrayHead = NOT_A_DICT_POS;
- fetchPtNodeInfo();
+ mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
} else {
mReadingState.mPos = NOT_A_DICT_POS;
}
@@ -201,13 +190,7 @@ class DynamicPatriciaTrieReadingHelper {
}
AK_FORCE_INLINE int getPosOfLastPtNodeArrayHead() const {
- return mReadingState.mPosOfLastPtNodeArrayHead;
- }
-
- AK_FORCE_INLINE void reloadCurrentPtNodeInfo() {
- if (!isEnd()) {
- fetchPtNodeInfo();
- }
+ return mReadingState.mPosOfThisPtNodeArrayHead;
}
bool traverseAllPtNodesInPostorderDepthFirstManner(TraversingEventListener *const listener);
@@ -218,50 +201,45 @@ class DynamicPatriciaTrieReadingHelper {
private:
DISALLOW_COPY_AND_ASSIGN(DynamicPatriciaTrieReadingHelper);
- class ReadingState {
+ // This class encapsulates the reading state of a position in the dictionary. It points at a
+ // specific PtNode in the dictionary.
+ class PtNodeReadingState {
public:
// Note that copy constructor and assignment operator are used for this class to use
// std::vector.
- ReadingState() : mPos(NOT_A_DICT_POS), mNodeCount(0), mPrevTotalCodePointCount(0),
- mTotalNodeCount(0), mNodeArrayCount(0), mPosOfLastForwardLinkField(NOT_A_DICT_POS),
- mPosOfLastPtNodeArrayHead(NOT_A_DICT_POS) {}
+ PtNodeReadingState() : mPos(NOT_A_DICT_POS), mRemainingPtNodeCountInThisArray(0),
+ mTotalCodePointCountSinceInitialization(0), mTotalPtNodeIndexInThisArrayChain(0),
+ mPtNodeArrayIndexInThisArrayChain(0), mPosOfLastForwardLinkField(NOT_A_DICT_POS),
+ mPosOfThisPtNodeArrayHead(NOT_A_DICT_POS) {}
int mPos;
- // Node count of a node array.
- int mNodeCount;
- int mPrevTotalCodePointCount;
- int mTotalNodeCount;
- int mNodeArrayCount;
+ // Remaining node count in the current array.
+ int mRemainingPtNodeCountInThisArray;
+ int mTotalCodePointCountSinceInitialization;
+ // Counter of PtNodes used to avoid infinite loops caused by broken or malicious links.
+ int mTotalPtNodeIndexInThisArrayChain;
+ // Counter of PtNode arrays used to avoid infinite loops caused by cyclic links of empty
+ // PtNode arrays.
+ int mPtNodeArrayIndexInThisArrayChain;
int mPosOfLastForwardLinkField;
- int mPosOfLastPtNodeArrayHead;
+ int mPosOfThisPtNodeArrayHead;
};
static const int MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP;
- static const int MAX_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP;
+ static const int MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP;
static const size_t MAX_READING_STATE_STACK_SIZE;
// TODO: Introduce error code to track what caused the error.
bool mIsError;
- ReadingState mReadingState;
+ PtNodeReadingState mReadingState;
const BufferWithExtendableBuffer *const mBuffer;
- DynamicPatriciaTrieNodeReader mNodeReader;
- int mMergedNodeCodePoints[MAX_WORD_LENGTH];
- std::vector<ReadingState> mReadingStateStack;
+ const PtNodeReader *const mPtNodeReader;
+ std::vector<PtNodeReadingState> mReadingStateStack;
void nextPtNodeArray();
void followForwardLink();
- AK_FORCE_INLINE void fetchPtNodeInfo() {
- mNodeReader.fetchNodeInfoInBufferFromPtNodePosAndGetNodeCodePoints(mReadingState.mPos,
- MAX_WORD_LENGTH, mMergedNodeCodePoints);
- if (mNodeReader.getCodePointCount() <= 0) {
- // Empty node is not allowed.
- mIsError = true;
- mReadingState.mPos = NOT_A_DICT_POS;
- }
- }
-
AK_FORCE_INLINE void pushReadingStateToStack() {
if (mReadingStateStack.size() > MAX_READING_STATE_STACK_SIZE) {
AKLOGI("Reading state stack overflow. Max size: %zd", MAX_READING_STATE_STACK_SIZE);
@@ -279,9 +257,6 @@ class DynamicPatriciaTrieReadingHelper {
} else {
mReadingState = mReadingStateStack.back();
mReadingStateStack.pop_back();
- if (!isEnd()) {
- fetchPtNodeInfo();
- }
}
}
};
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.cpp
index d68446db6..e94925365 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
#include "defines.h"
#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h
index 67c3cc57e..67c3cc57e 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.cpp
index 052558bfc..05caaebac 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.cpp
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h"
#include "suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_gc_event_listeners.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_helper.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_reader.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h"
#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/patricia_trie_reading_utils.h"
#include "suggest/policyimpl/dictionary/shortcut/dynamic_shortcut_list_policy.h"
#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
@@ -41,24 +41,26 @@ bool DynamicPatriciaTrieWritingHelper::addUnigramWord(
bool *const outAddedNewUnigram) {
int parentPos = NOT_A_DICT_POS;
while (!readingHelper->isEnd()) {
+ const PtNodeParams ptNodeParams(readingHelper->getPtNodeParams());
+ if (!ptNodeParams.isValid()) {
+ break;
+ }
const int matchedCodePointCount = readingHelper->getPrevTotalCodePointCount();
- if (!readingHelper->isMatchedCodePoint(0 /* index */,
+ if (!readingHelper->isMatchedCodePoint(ptNodeParams, 0 /* index */,
wordCodePoints[matchedCodePointCount])) {
// The first code point is different from target code point. Skip this node and read
// the next sibling node.
- readingHelper->readNextSiblingNode();
+ readingHelper->readNextSiblingNode(ptNodeParams);
continue;
}
// Check following merged node code points.
- const DynamicPatriciaTrieNodeReader *const nodeReader = readingHelper->getNodeReader();
- const int nodeCodePointCount = nodeReader->getCodePointCount();
+ const int nodeCodePointCount = ptNodeParams.getCodePointCount();
for (int j = 1; j < nodeCodePointCount; ++j) {
const int nextIndex = matchedCodePointCount + j;
- if (nextIndex >= codePointCount || !readingHelper->isMatchedCodePoint(j,
+ if (nextIndex >= codePointCount || !readingHelper->isMatchedCodePoint(ptNodeParams, j,
wordCodePoints[matchedCodePointCount + j])) {
*outAddedNewUnigram = true;
- return reallocatePtNodeAndAddNewPtNodes(nodeReader,
- readingHelper->getMergedNodeCodePoints(), j,
+ return reallocatePtNodeAndAddNewPtNodes(&ptNodeParams, j,
getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */,
probability),
wordCodePoints + matchedCodePointCount,
@@ -66,20 +68,19 @@ bool DynamicPatriciaTrieWritingHelper::addUnigramWord(
}
}
// All characters are matched.
- if (codePointCount == readingHelper->getTotalCodePointCount()) {
- return setPtNodeProbability(nodeReader, probability,
- readingHelper->getMergedNodeCodePoints(), outAddedNewUnigram);
+ if (codePointCount == readingHelper->getTotalCodePointCount(ptNodeParams)) {
+ return setPtNodeProbability(&ptNodeParams, probability, outAddedNewUnigram);
}
- if (!nodeReader->hasChildren()) {
+ if (!ptNodeParams.hasChildren()) {
*outAddedNewUnigram = true;
- return createChildrenPtNodeArrayAndAChildPtNode(nodeReader,
+ return createChildrenPtNodeArrayAndAChildPtNode(&ptNodeParams,
getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability),
- wordCodePoints + readingHelper->getTotalCodePointCount(),
- codePointCount - readingHelper->getTotalCodePointCount());
+ wordCodePoints + readingHelper->getTotalCodePointCount(ptNodeParams),
+ codePointCount - readingHelper->getTotalCodePointCount(ptNodeParams));
}
// Advance to the children nodes.
- parentPos = nodeReader->getHeadPos();
- readingHelper->readChildNode();
+ parentPos = ptNodeParams.getHeadPos();
+ readingHelper->readChildNode(ptNodeParams);
}
if (readingHelper->isError()) {
// The dictionary is invalid.
@@ -95,26 +96,24 @@ bool DynamicPatriciaTrieWritingHelper::addUnigramWord(
bool DynamicPatriciaTrieWritingHelper::addBigramWords(const int word0Pos, const int word1Pos,
const int probability, bool *const outAddedNewBigram) {
- int mMergedNodeCodePoints[MAX_WORD_LENGTH];
DynamicPatriciaTrieNodeReader nodeReader(mBuffer, mBigramPolicy, mShortcutPolicy);
- nodeReader.fetchNodeInfoInBufferFromPtNodePosAndGetNodeCodePoints(word0Pos, MAX_WORD_LENGTH,
- mMergedNodeCodePoints);
+ const PtNodeParams ptNodeParams(nodeReader.fetchNodeInfoInBufferFromPtNodePos(word0Pos));
// Move node to add bigram entry.
const int newNodePos = mBuffer->getTailPosition();
- if (!markNodeAsMovedAndSetPosition(&nodeReader, newNodePos, newNodePos)) {
+ if (!markNodeAsMovedAndSetPosition(&ptNodeParams, newNodePos, newNodePos)) {
return false;
}
int writingPos = newNodePos;
// Write a new PtNode using original PtNode's info to the tail of the dictionary in mBuffer.
- if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, &nodeReader, nodeReader.getParentPos(),
- mMergedNodeCodePoints, nodeReader.getCodePointCount(), nodeReader.getProbability(),
- &writingPos)) {
+ if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, &ptNodeParams, ptNodeParams.getParentPos(),
+ ptNodeParams.getCodePoints(), ptNodeParams.getCodePointCount(),
+ ptNodeParams.getProbability(), &writingPos)) {
return false;
}
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(newNodePos);
- if (nodeReader.getBigramsPos() != NOT_A_DICT_POS) {
+ const PtNodeParams newPtNodeParams(nodeReader.fetchNodeInfoInBufferFromPtNodePos(newNodePos));
+ if (newPtNodeParams.getBigramsPos() != NOT_A_DICT_POS) {
// Insert a new bigram entry into the existing bigram list.
- int bigramListPos = nodeReader.getBigramsPos();
+ int bigramListPos = newPtNodeParams.getBigramsPos();
return mBigramPolicy->addNewBigramEntryToBigramList(word1Pos, probability, &bigramListPos,
outAddedNewBigram);
} else {
@@ -126,10 +125,11 @@ bool DynamicPatriciaTrieWritingHelper::addBigramWords(const int word0Pos, const
}
// Then, Mark as the PtNode having bigram list in the flags.
const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
- PatriciaTrieReadingUtils::createAndGetFlags(nodeReader.isBlacklisted(),
- nodeReader.isNotAWord(), nodeReader.getProbability() != NOT_A_PROBABILITY,
- nodeReader.getShortcutPos() != NOT_A_DICT_POS, true /* hasBigrams */,
- nodeReader.getCodePointCount() > 1, CHILDREN_POSITION_FIELD_SIZE);
+ PatriciaTrieReadingUtils::createAndGetFlags(newPtNodeParams.isBlacklisted(),
+ newPtNodeParams.isNotAWord(),
+ newPtNodeParams.getProbability() != NOT_A_PROBABILITY,
+ newPtNodeParams.getShortcutPos() != NOT_A_DICT_POS, true /* hasBigrams */,
+ newPtNodeParams.getCodePointCount() > 1, CHILDREN_POSITION_FIELD_SIZE);
writingPos = newNodePos;
// Write updated flags into the moved PtNode's flags field.
return DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags,
@@ -140,16 +140,17 @@ bool DynamicPatriciaTrieWritingHelper::addBigramWords(const int word0Pos, const
// Remove a bigram relation from word0Pos to word1Pos.
bool DynamicPatriciaTrieWritingHelper::removeBigramWords(const int word0Pos, const int word1Pos) {
DynamicPatriciaTrieNodeReader nodeReader(mBuffer, mBigramPolicy, mShortcutPolicy);
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(word0Pos);
- if (nodeReader.getBigramsPos() == NOT_A_DICT_POS) {
+ const PtNodeParams ptNodeParams(nodeReader.fetchNodeInfoInBufferFromPtNodePos(word0Pos));
+ if (ptNodeParams.getBigramsPos() == NOT_A_DICT_POS) {
return false;
}
- return mBigramPolicy->removeBigram(nodeReader.getBigramsPos(), word1Pos);
+ return mBigramPolicy->removeBigram(ptNodeParams.getBigramsPos(), word1Pos);
}
void DynamicPatriciaTrieWritingHelper::writeToDictFile(const char *const fileName,
const HeaderPolicy *const headerPolicy, const int unigramCount, const int bigramCount) {
- BufferWithExtendableBuffer headerBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */);
+ BufferWithExtendableBuffer headerBuffer(
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
const int extendedRegionSize = headerPolicy->getExtendedRegionSize() +
mBuffer->getUsedAdditionalBufferSize();
if (!headerPolicy->writeHeaderToBuffer(&headerBuffer, false /* updatesLastUpdatedTime */,
@@ -161,8 +162,7 @@ void DynamicPatriciaTrieWritingHelper::writeToDictFile(const char *const fileNam
void DynamicPatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos,
const char *const fileName, const HeaderPolicy *const headerPolicy) {
- BufferWithExtendableBuffer newDictBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */,
- MAX_DICTIONARY_SIZE);
+ BufferWithExtendableBuffer newDictBuffer(MAX_DICTIONARY_SIZE);
int unigramCount = 0;
int bigramCount = 0;
if (mNeedsToDecay) {
@@ -171,7 +171,8 @@ void DynamicPatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNod
if (!runGC(rootPtNodeArrayPos, headerPolicy, &newDictBuffer, &unigramCount, &bigramCount)) {
return;
}
- BufferWithExtendableBuffer headerBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */);
+ BufferWithExtendableBuffer headerBuffer(
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
if (!headerPolicy->writeHeaderToBuffer(&headerBuffer, true /* updatesLastUpdatedTime */,
mNeedsToDecay, unigramCount, bigramCount, 0 /* extendedRegionSize */)) {
return;
@@ -180,8 +181,8 @@ void DynamicPatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNod
}
bool DynamicPatriciaTrieWritingHelper::markNodeAsDeleted(
- const DynamicPatriciaTrieNodeReader *const nodeToUpdate) {
- int pos = nodeToUpdate->getHeadPos();
+ const PtNodeParams *const toBeUpdatedPtNodeParams) {
+ int pos = toBeUpdatedPtNodeParams->getHeadPos();
const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(pos);
const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
if (usesAdditionalBuffer) {
@@ -193,16 +194,16 @@ bool DynamicPatriciaTrieWritingHelper::markNodeAsDeleted(
const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
true /* isDeleted */);
- int writingPos = nodeToUpdate->getHeadPos();
+ int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
// Update flags.
return DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags,
&writingPos);
}
bool DynamicPatriciaTrieWritingHelper::markNodeAsMovedAndSetPosition(
- const DynamicPatriciaTrieNodeReader *const originalNode, const int movedPos,
+ const PtNodeParams *const toBeUpdatedPtNodeParams, const int movedPos,
const int bigramLinkedNodePos) {
- int pos = originalNode->getHeadPos();
+ int pos = toBeUpdatedPtNodeParams->getHeadPos();
const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(pos);
const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
if (usesAdditionalBuffer) {
@@ -214,7 +215,7 @@ bool DynamicPatriciaTrieWritingHelper::markNodeAsMovedAndSetPosition(
const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */,
false /* isDeleted */);
- int writingPos = originalNode->getHeadPos();
+ int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
// Update flags.
if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags,
&writingPos)) {
@@ -222,31 +223,32 @@ bool DynamicPatriciaTrieWritingHelper::markNodeAsMovedAndSetPosition(
}
// Update moved position, which is stored in the parent offset field.
if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition(
- mBuffer, movedPos, originalNode->getHeadPos(), &writingPos)) {
+ mBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
return false;
}
// Update bigram linked node position, which is stored in the children position field.
- int childrenPosFieldPos = originalNode->getChildrenPosFieldPos();
+ int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos();
if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(
mBuffer, bigramLinkedNodePos, &childrenPosFieldPos)) {
return false;
}
- if (originalNode->hasChildren()) {
+ if (toBeUpdatedPtNodeParams->hasChildren()) {
// Update children's parent position.
- DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy);
- const DynamicPatriciaTrieNodeReader *const nodeReader = readingHelper.getNodeReader();
- readingHelper.initWithPtNodeArrayPos(originalNode->getChildrenPos());
+ DynamicPatriciaTrieNodeReader nodeReader(mBuffer, mBigramPolicy, mShortcutPolicy);
+ DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, &nodeReader);
+ readingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos());
while (!readingHelper.isEnd()) {
- int parentOffsetFieldPos = nodeReader->getHeadPos()
+ const PtNodeParams childPtNodeParams(readingHelper.getPtNodeParams());
+ int parentOffsetFieldPos = childPtNodeParams.getHeadPos()
+ DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE;
if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition(
- mBuffer, bigramLinkedNodePos, nodeReader->getHeadPos(),
+ mBuffer, bigramLinkedNodePos, childPtNodeParams.getHeadPos(),
&parentOffsetFieldPos)) {
// Parent offset cannot be written because of a bug or a broken dictionary; thus,
// we give up to update dictionary.
return false;
}
- readingHelper.readNextSiblingNode();
+ readingHelper.readNextSiblingNode(childPtNodeParams);
}
}
return true;
@@ -332,13 +334,13 @@ bool DynamicPatriciaTrieWritingHelper::writePtNodeToBuffer(
bool DynamicPatriciaTrieWritingHelper::writePtNodeToBufferByCopyingPtNodeInfo(
BufferWithExtendableBuffer *const bufferToWrite,
- const DynamicPatriciaTrieNodeReader *const originalNode, const int parentPos,
+ const PtNodeParams *const originalPtNodeParams, const int parentPos,
const int *const codePoints, const int codePointCount, const int probability,
int *const writingPos) {
- return writePtNodeWithFullInfoToBuffer(bufferToWrite, originalNode->isBlacklisted(),
- originalNode->isNotAWord(), parentPos, codePoints, codePointCount, probability,
- originalNode->getChildrenPos(), originalNode->getBigramsPos(),
- originalNode->getShortcutPos(), writingPos);
+ return writePtNodeWithFullInfoToBuffer(bufferToWrite, originalPtNodeParams->isBlacklisted(),
+ originalPtNodeParams->isNotAWord(), parentPos, codePoints, codePointCount, probability,
+ originalPtNodeParams->getChildrenPos(), originalPtNodeParams->getBigramsPos(),
+ originalPtNodeParams->getShortcutPos(), writingPos);
}
bool DynamicPatriciaTrieWritingHelper::createAndInsertNodeIntoPtNodeArray(const int parentPos,
@@ -354,14 +356,14 @@ bool DynamicPatriciaTrieWritingHelper::createAndInsertNodeIntoPtNodeArray(const
}
bool DynamicPatriciaTrieWritingHelper::setPtNodeProbability(
- const DynamicPatriciaTrieNodeReader *const originalPtNode, const int probability,
- const int *const codePoints, bool *const outAddedNewUnigram) {
- if (originalPtNode->isTerminal()) {
+ const PtNodeParams *const originalPtNodeParams, const int probability,
+ bool *const outAddedNewUnigram) {
+ if (originalPtNodeParams->isTerminal()) {
// Overwrites the probability.
*outAddedNewUnigram = false;
- const int probabilityToWrite = getUpdatedProbability(originalPtNode->getProbability(),
- probability);
- int probabilityFieldPos = originalPtNode->getProbabilityFieldPos();
+ const int probabilityToWrite = getUpdatedProbability(
+ originalPtNodeParams->getProbability(), probability);
+ int probabilityFieldPos = originalPtNodeParams->getProbabilityFieldPos();
if (!DynamicPatriciaTrieWritingUtils::writeProbabilityAndAdvancePosition(mBuffer,
probabilityToWrite, &probabilityFieldPos)) {
return false;
@@ -370,11 +372,12 @@ bool DynamicPatriciaTrieWritingHelper::setPtNodeProbability(
// Make the node terminal and write the probability.
*outAddedNewUnigram = true;
int movedPos = mBuffer->getTailPosition();
- if (!markNodeAsMovedAndSetPosition(originalPtNode, movedPos, movedPos)) {
+ if (!markNodeAsMovedAndSetPosition(originalPtNodeParams, movedPos, movedPos)) {
return false;
}
- if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, originalPtNode,
- originalPtNode->getParentPos(), codePoints, originalPtNode->getCodePointCount(),
+ if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, originalPtNodeParams,
+ originalPtNodeParams->getParentPos(), originalPtNodeParams->getCodePoints(),
+ originalPtNodeParams->getCodePointCount(),
getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability),
&movedPos)) {
return false;
@@ -384,15 +387,15 @@ bool DynamicPatriciaTrieWritingHelper::setPtNodeProbability(
}
bool DynamicPatriciaTrieWritingHelper::createChildrenPtNodeArrayAndAChildPtNode(
- const DynamicPatriciaTrieNodeReader *const parentNode, const int probability,
+ const PtNodeParams *const parentPtNodeParams, const int probability,
const int *const codePoints, const int codePointCount) {
const int newPtNodeArrayPos = mBuffer->getTailPosition();
- int childrenPosFieldPos = parentNode->getChildrenPosFieldPos();
+ int childrenPosFieldPos = parentPtNodeParams->getChildrenPosFieldPos();
if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBuffer,
newPtNodeArrayPos, &childrenPosFieldPos)) {
return false;
}
- return createNewPtNodeArrayWithAChildPtNode(parentNode->getHeadPos(), codePoints,
+ return createNewPtNodeArrayWithAChildPtNode(parentPtNodeParams->getHeadPos(), codePoints,
codePointCount, probability);
}
@@ -417,8 +420,7 @@ bool DynamicPatriciaTrieWritingHelper::createNewPtNodeArrayWithAChildPtNode(
// Returns whether the dictionary updating was succeeded or not.
bool DynamicPatriciaTrieWritingHelper::reallocatePtNodeAndAddNewPtNodes(
- const DynamicPatriciaTrieNodeReader *const reallocatingPtNode,
- const int *const reallocatingPtNodeCodePoints, const int overlappingCodePointCount,
+ const PtNodeParams *const reallocatingPtNodeParams, const int overlappingCodePointCount,
const int probabilityOfNewPtNode, const int *const newNodeCodePoints,
const int newNodeCodePointCount) {
// When addsExtraChild is true, split the reallocating PtNode and add new child.
@@ -434,8 +436,8 @@ bool DynamicPatriciaTrieWritingHelper::reallocatePtNodeAndAddNewPtNodes(
// Write the 1st part of the reallocating node. The children position will be updated later
// with actual children position.
const int newProbability = addsExtraChild ? NOT_A_PROBABILITY : probabilityOfNewPtNode;
- if (!writePtNodeToBuffer(mBuffer, reallocatingPtNode->getParentPos(),
- reallocatingPtNodeCodePoints, overlappingCodePointCount, newProbability,
+ if (!writePtNodeToBuffer(mBuffer, reallocatingPtNodeParams->getParentPos(),
+ reallocatingPtNodeParams->getCodePoints(), overlappingCodePointCount, newProbability,
&writingPos)) {
return false;
}
@@ -448,11 +450,11 @@ bool DynamicPatriciaTrieWritingHelper::reallocatePtNodeAndAddNewPtNodes(
}
// Write the 2nd part of the reallocating node.
const int secondPartOfReallocatedPtNodePos = writingPos;
- if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, reallocatingPtNode,
+ if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, reallocatingPtNodeParams,
firstPartOfReallocatedPtNodePos,
- reallocatingPtNodeCodePoints + overlappingCodePointCount,
- reallocatingPtNode->getCodePointCount() - overlappingCodePointCount,
- reallocatingPtNode->getProbability(), &writingPos)) {
+ reallocatingPtNodeParams->getCodePoints() + overlappingCodePointCount,
+ reallocatingPtNodeParams->getCodePointCount() - overlappingCodePointCount,
+ reallocatingPtNodeParams->getProbability(), &writingPos)) {
return false;
}
if (addsExtraChild) {
@@ -467,16 +469,17 @@ bool DynamicPatriciaTrieWritingHelper::reallocatePtNodeAndAddNewPtNodes(
NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
return false;
}
- // Update original reallocatingPtNode as moved.
- if (!markNodeAsMovedAndSetPosition(reallocatingPtNode, firstPartOfReallocatedPtNodePos,
+ // Update original reallocating PtNode as moved.
+ if (!markNodeAsMovedAndSetPosition(reallocatingPtNodeParams, firstPartOfReallocatedPtNodePos,
secondPartOfReallocatedPtNodePos)) {
return false;
}
// Load node info. Information of the 1st part will be fetched.
DynamicPatriciaTrieNodeReader nodeReader(mBuffer, mBigramPolicy, mShortcutPolicy);
- nodeReader.fetchNodeInfoInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos);
+ const PtNodeParams ptNodeParams(
+ nodeReader.fetchNodeInfoInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos));
// Update children position.
- int childrenPosFieldPos = nodeReader.getChildrenPosFieldPos();
+ int childrenPosFieldPos = ptNodeParams.getChildrenPosFieldPos();
if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBuffer,
actualChildrenPos, &childrenPosFieldPos)) {
return false;
@@ -487,7 +490,8 @@ bool DynamicPatriciaTrieWritingHelper::reallocatePtNodeAndAddNewPtNodes(
bool DynamicPatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
const HeaderPolicy *const headerPolicy, BufferWithExtendableBuffer *const bufferToWrite,
int *const outUnigramCount, int *const outBigramCount) {
- DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy);
+ DynamicPatriciaTrieNodeReader nodeReader(mBuffer, mBigramPolicy, mShortcutPolicy);
+ DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, &nodeReader);
readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
DynamicPatriciaTrieGcEventListeners
::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
@@ -529,9 +533,10 @@ bool DynamicPatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
DynamicShortcutListPolicy newDictShortcutPolicy(bufferToWrite);
DynamicBigramListPolicy newDictBigramPolicy(headerPolicy, bufferToWrite, &newDictShortcutPolicy,
mNeedsToDecay);
- // Create reading helper for the GCed dictionary.
- DynamicPatriciaTrieReadingHelper newDictReadingHelper(bufferToWrite, &newDictBigramPolicy,
+ // Create reading node reader and reading helper for the GCed dictionary.
+ DynamicPatriciaTrieNodeReader newDictNodeReader(bufferToWrite, &newDictBigramPolicy,
&newDictShortcutPolicy);
+ DynamicPatriciaTrieReadingHelper newDictReadingHelper(bufferToWrite, &newDictNodeReader);
newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionFields
traversePolicyToUpdateAllPositionFields(this, &newDictBigramPolicy, bufferToWrite,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h
index ca8664729..5614cb3ac 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h
@@ -26,11 +26,12 @@ namespace latinime {
class BufferWithExtendableBuffer;
class DynamicBigramListPolicy;
-class DynamicPatriciaTrieNodeReader;
class DynamicPatriciaTrieReadingHelper;
class DynamicShortcutListPolicy;
class HeaderPolicy;
+class PtNodeParams;
+// TODO: Make it independent from a particular format and move to pt_common.
class DynamicPatriciaTrieWritingHelper {
public:
typedef hash_map_compat<int, int> PtNodeArrayPositionRelocationMap;
@@ -77,12 +78,12 @@ class DynamicPatriciaTrieWritingHelper {
// CAVEAT: This method must be called only from inner classes of
// DynamicPatriciaTrieGcEventListeners.
- bool markNodeAsDeleted(const DynamicPatriciaTrieNodeReader *const nodeToUpdate);
+ bool markNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams);
// CAVEAT: This method must be called only from this class or inner classes of
// DynamicPatriciaTrieGcEventListeners.
bool writePtNodeToBufferByCopyingPtNodeInfo(BufferWithExtendableBuffer *const bufferToWrite,
- const DynamicPatriciaTrieNodeReader *const originalNode, const int parentPos,
+ const PtNodeParams *const originalPtNodeParams, const int parentPos,
const int *const codePoints, const int codePointCount, const int probability,
int *const writingPos);
@@ -96,7 +97,7 @@ class DynamicPatriciaTrieWritingHelper {
DynamicShortcutListPolicy *const mShortcutPolicy;
const bool mNeedsToDecay;
- bool markNodeAsMovedAndSetPosition(const DynamicPatriciaTrieNodeReader *const nodeToUpdate,
+ bool markNodeAsMovedAndSetPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
const int movedPos, const int bigramLinkedNodePos);
bool writePtNodeWithFullInfoToBuffer(BufferWithExtendableBuffer *const bufferToWrite,
@@ -112,19 +113,17 @@ class DynamicPatriciaTrieWritingHelper {
bool createAndInsertNodeIntoPtNodeArray(const int parentPos, const int *const nodeCodePoints,
const int nodeCodePointCount, const int probability, int *const forwardLinkFieldPos);
- bool setPtNodeProbability(const DynamicPatriciaTrieNodeReader *const originalNode,
- const int probability, const int *const codePoints, bool *const outAddedNewUnigram);
+ bool setPtNodeProbability(const PtNodeParams *const originalPtNodeParams, const int probability,
+ bool *const outAddedNewUnigram);
- bool createChildrenPtNodeArrayAndAChildPtNode(
- const DynamicPatriciaTrieNodeReader *const parentNode, const int probability,
- const int *const codePoints, const int codePointCount);
+ bool createChildrenPtNodeArrayAndAChildPtNode(const PtNodeParams *const parentPtNodeParams,
+ const int probability, const int *const codePoints, const int codePointCount);
bool createNewPtNodeArrayWithAChildPtNode(const int parentPos, const int *const nodeCodePoints,
const int nodeCodePointCount, const int probability);
bool reallocatePtNodeAndAddNewPtNodes(
- const DynamicPatriciaTrieNodeReader *const reallocatingPtNode,
- const int *const reallocatingPtNodeCodePoints, const int overlappingCodePointCount,
+ const PtNodeParams *const reallocatingPtNodeParams, const int overlappingCodePointCount,
const int probabilityOfNewPtNode, const int *const newNodeCodePoints,
const int newNodeCodePointCount);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.cpp
index 30ff10cd6..67733660b 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h"
#include <cstddef>
#include <cstdlib>
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h
index af76bc6b5..5654105ee 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h
@@ -20,7 +20,7 @@
#include <cstddef>
#include "defines.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_utils.h"
namespace latinime {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dict_content.h
new file mode 100644
index 000000000..0c2f47073
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/dict_content.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_DICT_CONTENT_H
+#define LATINIME_DICT_CONTENT_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class DictContent {
+ public:
+ virtual ~DictContent() {}
+ virtual bool isValid() const = 0;
+
+ protected:
+ DictContent() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DictContent);
+};
+} // namespace latinime
+#endif /* LATINIME_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
new file mode 100644
index 000000000..e415881a9
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SINGLE_DICT_CONTENT_H
+#define LATINIME_SINGLE_DICT_CONTENT_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/v4/content/dict_content.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+
+class SingleDictContent : public DictContent {
+ public:
+ SingleDictContent(const char *const dictDirPath, const char *const contentFileName,
+ const bool isUpdatable)
+ : mMmappedBuffer(MmappedBuffer::openBuffer(dictDirPath, contentFileName, isUpdatable)),
+ mExpandableContentBuffer(mMmappedBuffer.get() ? mMmappedBuffer.get()->getBuffer() : 0,
+ mMmappedBuffer.get() ? mMmappedBuffer.get()->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {}
+
+ virtual ~SingleDictContent() {}
+
+ virtual bool isValid() const {
+ return mMmappedBuffer.get() != 0;
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SingleDictContent);
+
+ const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
+ BufferWithExtendableBuffer mExpandableContentBuffer;
+};
+} // namespace latinime
+#endif /* LATINIME_SINGLE_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h
new file mode 100644
index 000000000..446b51ed0
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SPARSE_TABLE_DICT_CONTENT_H
+#define LATINIME_SPARSE_TABLE_DICT_CONTENT_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/v4/content/dict_content.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+
+// TODO: Support multiple contents.
+class SparseTableDictContent : public DictContent {
+ public:
+ AK_FORCE_INLINE SparseTableDictContent(const char *const dictDirPath,
+ const char *const lookupTableFileName, const char *const addressTableFileName,
+ const char *const contentFileName, const bool isUpdatable)
+ : mLookupTableBuffer(
+ MmappedBuffer::openBuffer(dictDirPath, lookupTableFileName, isUpdatable)),
+ mAddressTableBuffer(
+ MmappedBuffer::openBuffer(dictDirPath, addressTableFileName, isUpdatable)),
+ mContentBuffer(MmappedBuffer::openBuffer(dictDirPath, contentFileName, isUpdatable)),
+ mExpandableLookupTableBuffer(
+ mLookupTableBuffer.get() ? mLookupTableBuffer.get()->getBuffer() : 0,
+ mLookupTableBuffer.get() ? mLookupTableBuffer.get()->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mExpandableAddressTableBuffer(
+ mAddressTableBuffer.get() ? mAddressTableBuffer.get()->getBuffer() : 0,
+ mAddressTableBuffer.get() ? mAddressTableBuffer.get()->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+ mExpandableContentBuffer(mContentBuffer.get() ? mContentBuffer.get()->getBuffer() : 0,
+ mContentBuffer.get() ? mContentBuffer.get()->getBufferSize() : 0,
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {}
+
+ virtual ~SparseTableDictContent() {}
+
+ virtual bool isValid() const {
+ return mLookupTableBuffer.get() != 0 && mAddressTableBuffer.get() != 0
+ && mContentBuffer.get() != 0;
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTableDictContent);
+
+ // TODO: Have sparse table.
+ const MmappedBuffer::MmappedBufferPtr mLookupTableBuffer;
+ const MmappedBuffer::MmappedBufferPtr mAddressTableBuffer;
+ const MmappedBuffer::MmappedBufferPtr mContentBuffer;
+ BufferWithExtendableBuffer mExpandableLookupTableBuffer;
+ BufferWithExtendableBuffer mExpandableAddressTableBuffer;
+ BufferWithExtendableBuffer mExpandableContentBuffer;
+};
+} // namespace latinime
+#endif /* LATINIME_SPARSE_TABLE_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
new file mode 100644
index 000000000..1164c408a
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_DICT_BUFFER_H
+#define LATINIME_VER4_DICT_BUFFER_H
+
+#include "defines.h"
+#include "suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h"
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+
+class Ver4DictBuffers {
+ public:
+ typedef ExclusiveOwnershipPointer<Ver4DictBuffers> Ver4DictBuffersPtr;
+
+ static Ver4DictBuffersPtr openVer4DictBuffers(const char *const dictDirPath,
+ const MmappedBuffer::MmappedBufferPtr &dictBuffer) {
+ const bool isUpdatable = dictBuffer.get() ? dictBuffer.get()->isUpdatable() : false;
+ return Ver4DictBuffersPtr(new Ver4DictBuffers(dictDirPath, dictBuffer, isUpdatable));
+ }
+
+ AK_FORCE_INLINE bool isValid() const {
+ return mDictBuffer.get() != 0 && mProbabilityDictContent.isValid()
+ && mTerminalAddressTable.isValid() && mBigramDictContent.isValid()
+ && mShortcutDictContent.isValid();
+ }
+
+ AK_FORCE_INLINE const uint8_t *getRawDictBuffer() const {
+ return mDictBuffer.get()->getBuffer();
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4DictBuffers);
+
+ AK_FORCE_INLINE Ver4DictBuffers(const char *const dictDirPath,
+ const MmappedBuffer::MmappedBufferPtr &dictBuffer, const bool isUpdatable)
+ : mDictBuffer(dictBuffer),
+ mTerminalAddressTable(dictDirPath,
+ Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION, isUpdatable),
+ mProbabilityDictContent(dictDirPath, Ver4DictConstants::FREQ_FILE_EXTENSION,
+ isUpdatable),
+ mBigramDictContent(dictDirPath,
+ Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::BIGRAM_FILE_EXTENSION, isUpdatable),
+ mShortcutDictContent(dictDirPath,
+ Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION,
+ Ver4DictConstants::SHORTCUT_FILE_EXTENSION, isUpdatable) {}
+
+ const MmappedBuffer::MmappedBufferPtr mDictBuffer;
+ SingleDictContent mTerminalAddressTable;
+ SingleDictContent mProbabilityDictContent;
+ SparseTableDictContent mBigramDictContent;
+ SparseTableDictContent mShortcutDictContent;
+};
+} // namespace latinime
+#endif /* LATINIME_VER4_DICT_BUFFER_H */
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
new file mode 100644
index 000000000..0bfd07b04
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+
+const char *const Ver4DictConstants::TRIE_FILE_EXTENSION = ".trie";
+const char *const Ver4DictConstants::FREQ_FILE_EXTENSION = ".freq";
+// tat = Terminal Address Table
+const char *const Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION = ".tat";
+const char *const Ver4DictConstants::BIGRAM_FILE_EXTENSION = ".bigram_freq";
+const char *const Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION = ".bigram_lookup";
+const char *const Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION = ".bigram_index_freq";
+const char *const Ver4DictConstants::SHORTCUT_FILE_EXTENSION = ".shortcut_shortcut";
+const char *const Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION = ".shortcut_lookup";
+const char *const Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION =
+ ".shortcut_index_shortcut";
+
+const int Ver4DictConstants::NOT_A_TERMINAL = -1;
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
new file mode 100644
index 000000000..6498ce428
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_DICT_CONSTANTS_H
+#define LATINIME_VER4_DICT_CONSTANTS_H
+
+#include "defines.h"
+
+namespace latinime {
+
+// Note that there are corresponding definitions in FormatSpec.java.
+class Ver4DictConstants {
+ public:
+ static const char *const TRIE_FILE_EXTENSION;
+ static const char *const FREQ_FILE_EXTENSION;
+ static const char *const TERMINAL_ADDRESS_TABLE_FILE_EXTENSION;
+ static const char *const BIGRAM_FILE_EXTENSION;
+ static const char *const BIGRAM_LOOKUP_TABLE_FILE_EXTENSION;
+ static const char *const BIGRAM_CONTENT_TABLE_FILE_EXTENSION;
+ static const char *const SHORTCUT_FILE_EXTENSION;
+ static const char *const SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION;
+ static const char *const SHORTCUT_CONTENT_TABLE_FILE_EXTENSION;
+
+ static const int NOT_A_TERMINAL;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4DictConstants);
+};
+} // namespace latinime
+#endif /* LATINIME_VER4_DICT_CONSTANTS_H */
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
new file mode 100644
index 000000000..b9ee4891c
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h"
+
+namespace latinime {
+
+void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
+ DicNodeVector *const childDicNodes) const {
+ // TODO: Implement.
+}
+
+int Ver4PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
+ const int ptNodePos, const int maxCodePointCount, int *const outCodePoints,
+ int *const outUnigramProbability) const {
+ // TODO: Implement.
+ return 0;
+}
+
+int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
+ const int length, const bool forceLowerCaseSearch) const {
+ // TODO: Implement.
+ return NOT_A_DICT_POS;
+}
+
+int Ver4PatriciaTriePolicy::getProbability(const int unigramProbability,
+ const int bigramProbability) const {
+ // TODO: Implement.
+ return NOT_A_PROBABILITY;
+}
+
+int Ver4PatriciaTriePolicy::getUnigramProbabilityOfPtNode(const int ptNodePos) const {
+ // TODO: Implement.
+ return NOT_A_PROBABILITY;
+}
+
+int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
+ // TODO: Implement.
+ return NOT_A_DICT_POS;
+}
+
+int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
+ // TODO: Implement.
+ return NOT_A_DICT_POS;
+}
+
+bool Ver4PatriciaTriePolicy::addUnigramWord(const int *const word, const int length,
+ const int probability) {
+ // TODO: Implement.
+ return false;
+}
+
+bool Ver4PatriciaTriePolicy::addBigramWords(const int *const word0, const int length0,
+ const int *const word1, const int length1, const int probability) {
+ // TODO: Implement.
+ return false;
+}
+
+bool Ver4PatriciaTriePolicy::removeBigramWords(const int *const word0, const int length0,
+ const int *const word1, const int length1) {
+ // TODO: Implement.
+ return false;
+}
+
+void Ver4PatriciaTriePolicy::flush(const char *const filePath) {
+ // TODO: Implement.
+}
+
+void Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) {
+ // TODO: Implement.
+}
+
+bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
+ // TODO: Implement.
+ return false;
+}
+
+void Ver4PatriciaTriePolicy::getProperty(const char *const query, char *const outResult,
+ const int maxResultLength) {
+ // TODO: Implement.
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
new file mode 100644
index 000000000..f7bfb3b0d
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_PATRICIA_TRIE_POLICY_H
+#define LATINIME_VER4_PATRICIA_TRIE_POLICY_H
+
+#include "defines.h"
+#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "suggest/policyimpl/dictionary/header/header_policy.h"
+#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
+#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+class DicNode;
+class DicNodeVector;
+
+// TODO: Implement.
+class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
+ public:
+ Ver4PatriciaTriePolicy(const Ver4DictBuffers::Ver4DictBuffersPtr &buffers)
+ : mBuffers(buffers),
+ mHeaderPolicy(mBuffers.get()->getRawDictBuffer(), FormatUtils::VERSION_4) {};
+
+ AK_FORCE_INLINE int getRootPosition() const {
+ return 0;
+ }
+
+ void createAndGetAllChildDicNodes(const DicNode *const dicNode,
+ DicNodeVector *const childDicNodes) const;
+
+ int getCodePointsAndProbabilityAndReturnCodePointCount(
+ const int terminalPtNodePos, const int maxCodePointCount, int *const outCodePoints,
+ int *const outUnigramProbability) const;
+
+ int getTerminalPtNodePositionOfWord(const int *const inWord,
+ const int length, const bool forceLowerCaseSearch) const;
+
+ int getProbability(const int unigramProbability, const int bigramProbability) const;
+
+ int getUnigramProbabilityOfPtNode(const int ptNodePos) const;
+
+ int getShortcutPositionOfPtNode(const int ptNodePos) const;
+
+ int getBigramsPositionOfPtNode(const int ptNodePos) const;
+
+ const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
+ return &mHeaderPolicy;
+ }
+
+ const DictionaryBigramsStructurePolicy *getBigramsStructurePolicy() const {
+ return 0;
+ }
+
+ const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const {
+ return 0;
+ }
+
+ bool addUnigramWord(const int *const word, const int length, const int probability);
+
+ bool addBigramWords(const int *const word0, const int length0, const int *const word1,
+ const int length1, const int probability);
+
+ bool removeBigramWords(const int *const word0, const int length0, const int *const word1,
+ const int length1);
+
+ void flush(const char *const filePath);
+
+ void flushWithGC(const char *const filePath);
+
+ bool needsToRunGC(const bool mindsBlockByGC) const;
+
+ void getProperty(const char *const query, char *const outResult,
+ const int maxResultLength);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTriePolicy);
+
+ const Ver4DictBuffers::Ver4DictBuffersPtr mBuffers;
+ const HeaderPolicy mHeaderPolicy;
+};
+} // namespace latinime
+#endif // LATINIME_VER4_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp
index f692882f2..5032131ab 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp
@@ -18,7 +18,7 @@
namespace latinime {
-const size_t BufferWithExtendableBuffer::MAX_ADDITIONAL_BUFFER_SIZE = 1024 * 1024;
+const size_t BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE = 1024 * 1024;
const int BufferWithExtendableBuffer::NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE = 90;
// TODO: Needs to allocate larger memory corresponding to the current vector size.
const size_t BufferWithExtendableBuffer::EXTEND_ADDITIONAL_BUFFER_SIZE_STEP = 128 * 1024;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
index 9dc34823c..1e27a1bec 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
@@ -32,12 +32,20 @@ namespace latinime {
// raw pointer but provides several methods that handle boundary checking for writing data.
class BufferWithExtendableBuffer {
public:
+ static const size_t DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE;
+
BufferWithExtendableBuffer(uint8_t *const originalBuffer, const int originalBufferSize,
- const int maxAdditionalBufferSize = MAX_ADDITIONAL_BUFFER_SIZE)
+ const int maxAdditionalBufferSize)
: mOriginalBuffer(originalBuffer), mOriginalBufferSize(originalBufferSize),
mAdditionalBuffer(EXTEND_ADDITIONAL_BUFFER_SIZE_STEP), mUsedAdditionalBufferSize(0),
mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
+ // Without original buffer.
+ BufferWithExtendableBuffer(const int maxAdditionalBufferSize)
+ : mOriginalBuffer(0), mOriginalBufferSize(0),
+ mAdditionalBuffer(EXTEND_ADDITIONAL_BUFFER_SIZE_STEP), mUsedAdditionalBufferSize(0),
+ mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
+
AK_FORCE_INLINE int getTailPosition() const {
return mOriginalBufferSize + mUsedAdditionalBufferSize;
}
@@ -86,7 +94,6 @@ class BufferWithExtendableBuffer {
private:
DISALLOW_COPY_AND_ASSIGN(BufferWithExtendableBuffer);
- static const size_t MAX_ADDITIONAL_BUFFER_SIZE;
static const int NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE;
static const size_t EXTEND_ADDITIONAL_BUFFER_SIZE_STEP;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
index 994826fa8..b48e5b005 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
@@ -20,7 +20,7 @@
#include <cstring>
#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_utils.h"
+#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h"
#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
#include "suggest/policyimpl/dictionary/utils/format_utils.h"
@@ -33,6 +33,9 @@ const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE =
switch (dictVersion) {
case 3:
return createEmptyV3DictFile(filePath, attributeMap);
+ case 4:
+ // TODO: Support version 4 dictionary format.
+ return false;
default:
// Only version 3 dictionary is supported for now.
return false;
@@ -41,12 +44,14 @@ const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE =
/* static */ bool DictFileWritingUtils::createEmptyV3DictFile(const char *const filePath,
const HeaderReadWriteUtils::AttributeMap *const attributeMap) {
- BufferWithExtendableBuffer headerBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */);
+ BufferWithExtendableBuffer headerBuffer(
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
HeaderPolicy headerPolicy(FormatUtils::VERSION_3, attributeMap);
headerPolicy.writeHeaderToBuffer(&headerBuffer, true /* updatesLastUpdatedTime */,
true /* updatesLastDecayedTime */, 0 /* unigramCount */, 0 /* bigramCount */,
0 /* extendedRegionSize */);
- BufferWithExtendableBuffer bodyBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */);
+ BufferWithExtendableBuffer bodyBuffer(
+ BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
if (!DynamicPatriciaTrieWritingUtils::writeEmptyDictionary(&bodyBuffer, 0 /* rootPos */)) {
return false;
}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.h
new file mode 100644
index 000000000..59b894fa6
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_FILE_UTILS_H
+#define LATINIME_FILE_UTILS_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "defines.h"
+
+namespace latinime {
+
+class FileUtils {
+ public:
+ // Returns -1 on error.
+ static int getFileSize(const char *const filePath) {
+ const int fd = open(filePath, O_RDONLY);
+ if (fd == -1) {
+ return -1;
+ }
+ struct stat statBuf;
+ if (fstat(fd, &statBuf) != 0) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return static_cast<int>(statBuf.st_size);
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FileUtils);
+};
+} // namespace latinime
+#endif /* LATINIME_FILE_UTILS_H */
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 1d77d5c27..4843650ad 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
@@ -45,6 +45,8 @@ const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
return VERSION_2;
} else if (ByteArrayUtils::readUint16(dict, 4) == 3) {
return VERSION_3;
+ } else if (ByteArrayUtils::readUint16(dict, 4) == 4) {
+ return VERSION_4;
} else {
return UNKNOWN_VERSION;
}
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 79ed0de29..b90393a53 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
@@ -31,6 +31,7 @@ class FormatUtils {
enum FORMAT_VERSION {
VERSION_2,
VERSION_3,
+ VERSION_4,
UNKNOWN_VERSION
};
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp
new file mode 100644
index 000000000..71f863290
--- /dev/null
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstdio>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "suggest/policyimpl/dictionary/utils/file_utils.h"
+
+namespace latinime {
+
+/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
+ const char *const path, const int bufferOffset, const int bufferSize,
+ const bool isUpdatable) {
+ const int openMode = isUpdatable ? O_RDWR : O_RDONLY;
+ const int mmapFd = open(path, openMode);
+ if (mmapFd < 0) {
+ AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
+ return MmappedBufferPtr(0);
+ }
+ const int pagesize = getpagesize();
+ const int offset = bufferOffset % pagesize;
+ int alignedOffset = bufferOffset - offset;
+ int alignedSize = bufferSize + offset;
+ const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ;
+ void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd,
+ alignedOffset);
+ if (mmappedBuffer == MAP_FAILED) {
+ AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
+ close(mmapFd);
+ return MmappedBufferPtr(0);
+ }
+ uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
+ if (!buffer) {
+ AKLOGE("DICT: buffer is null");
+ close(mmapFd);
+ return MmappedBufferPtr(0);
+ }
+ return MmappedBufferPtr(new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize,
+ mmapFd, isUpdatable));
+}
+
+/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
+ const char *const path, const bool isUpdatable) {
+ const int fileSize = FileUtils::getFileSize(path);
+ if (fileSize == -1) {
+ return MmappedBufferPtr(0);
+ } else if (fileSize == 0) {
+ return MmappedBufferPtr(new MmappedBuffer(isUpdatable));
+ } else {
+ return openBuffer(path, 0 /* bufferOffset */, fileSize, isUpdatable);
+ }
+}
+
+/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
+ const char *const dirPath, const char *const fileName, const bool isUpdatable) {
+ const int filePathBufferSize = PATH_MAX + 1 /* terminator */;
+ char filePath[filePathBufferSize];
+ const int filePathLength = snprintf(filePath, filePathBufferSize, "%s%s", dirPath,
+ fileName);
+ if (filePathLength >= filePathBufferSize) {
+ return 0;
+ }
+ return openBuffer(filePath, isUpdatable);
+}
+
+MmappedBuffer::~MmappedBuffer() {
+ if (mAlignedSize == 0) {
+ return;
+ }
+ int ret = munmap(mMmappedBuffer, mAlignedSize);
+ if (ret != 0) {
+ AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
+ }
+ ret = close(mMmapFd);
+ if (ret != 0) {
+ AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
+ }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.h b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.h
index 6b69116eb..73a733b0c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.h
@@ -17,58 +17,27 @@
#ifndef LATINIME_MMAPPED_BUFFER_H
#define LATINIME_MMAPPED_BUFFER_H
-#include <cerrno>
-#include <fcntl.h>
#include <stdint.h>
-#include <sys/mman.h>
-#include <unistd.h>
#include "defines.h"
+#include "utils/exclusive_ownership_pointer.h"
namespace latinime {
class MmappedBuffer {
public:
- static MmappedBuffer* openBuffer(const char *const path, const int bufferOffset,
- const int bufferSize, const bool isUpdatable) {
- const int openMode = isUpdatable ? O_RDWR : O_RDONLY;
- const int mmapFd = open(path, openMode);
- if (mmapFd < 0) {
- AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
- return 0;
- }
- const int pagesize = getpagesize();
- const int offset = bufferOffset % pagesize;
- int alignedOffset = bufferOffset - offset;
- int alignedSize = bufferSize + offset;
- const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ;
- void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd,
- alignedOffset);
- if (mmappedBuffer == MAP_FAILED) {
- AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
- close(mmapFd);
- return 0;
- }
- uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
- if (!buffer) {
- AKLOGE("DICT: buffer is null");
- close(mmapFd);
- return 0;
- }
- return new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize, mmapFd,
- isUpdatable);
- }
+ typedef ExclusiveOwnershipPointer<MmappedBuffer> MmappedBufferPtr;
- ~MmappedBuffer() {
- int ret = munmap(mMmappedBuffer, mAlignedSize);
- if (ret != 0) {
- AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
- }
- ret = close(mMmapFd);
- if (ret != 0) {
- AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
- }
- }
+ static MmappedBufferPtr openBuffer(const char *const path,
+ const int bufferOffset, const int bufferSize, const bool isUpdatable);
+
+ // Mmap entire file.
+ static MmappedBufferPtr openBuffer(const char *const path, const bool isUpdatable);
+
+ static MmappedBufferPtr openBuffer(const char *const dirPath, const char *const fileName,
+ const bool isUpdatable);
+
+ ~MmappedBuffer();
AK_FORCE_INLINE uint8_t *getBuffer() const {
return mBuffer;
@@ -89,6 +58,11 @@ class MmappedBuffer {
: mBuffer(buffer), mBufferSize(bufferSize), mMmappedBuffer(mmappedBuffer),
mAlignedSize(alignedSize), mMmapFd(mmapFd), mIsUpdatable(isUpdatable) {}
+ // Empty file. We have to handle an empty file as a valid part of a dictionary.
+ AK_FORCE_INLINE MmappedBuffer(const bool isUpdatable)
+ : mBuffer(0), mBufferSize(0), mMmappedBuffer(0), mAlignedSize(0), mMmapFd(0),
+ mIsUpdatable(isUpdatable) {}
+
DISALLOW_IMPLICIT_CONSTRUCTORS(MmappedBuffer);
uint8_t *const mBuffer;
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
index 007c19e0a..fd0ac9eb6 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -81,7 +81,7 @@ class TypingTraversal : public Traversal {
return false;
}
const int point0Index = dicNode->getInputIndex(0);
- return dicNode->isTerminalWordNode()
+ return dicNode->isTerminalDicNode()
&& traverseSession->getProximityInfoState(0)->
hasSpaceProximity(point0Index);
}
@@ -96,7 +96,7 @@ class TypingTraversal : public Traversal {
if (dicNode->isCompletion(inputSize)) {
return false;
}
- if (!dicNode->isTerminalWordNode()) {
+ if (!dicNode->isTerminalDicNode()) {
return false;
}
const int16_t pointIndex = dicNode->getInputIndex(0);
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
index 5b6b5e874..54f65c786 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
@@ -23,39 +23,64 @@ namespace latinime {
const TypingWeighting TypingWeighting::sInstance;
-ErrorType TypingWeighting::getErrorType(const CorrectionType correctionType,
+ErrorTypeUtils::ErrorType TypingWeighting::getErrorType(const CorrectionType correctionType,
const DicTraverseSession *const traverseSession, const DicNode *const parentDicNode,
const DicNode *const dicNode) const {
switch (correctionType) {
case CT_MATCH:
if (isProximityDicNode(traverseSession, dicNode)) {
- return ET_PROXIMITY_CORRECTION;
+ return ErrorTypeUtils::PROXIMITY_CORRECTION;
+ } else if (dicNode->isInDigraph()) {
+ return ErrorTypeUtils::MATCH_WITH_DIGRAPH;
} else {
- return ET_NOT_AN_ERROR;
+ // Compare the node code point with original primary code point on the keyboard.
+ const ProximityInfoState *const pInfoState =
+ traverseSession->getProximityInfoState(0);
+ const int primaryOriginalCodePoint = pInfoState->getPrimaryOriginalCodePointAt(
+ dicNode->getInputIndex(0));
+ const int nodeCodePoint = dicNode->getNodeCodePoint();
+ if (primaryOriginalCodePoint == nodeCodePoint) {
+ // Node code point is same as original code point on the keyboard.
+ return ErrorTypeUtils::NOT_AN_ERROR;
+ } else if (CharUtils::toLowerCase(primaryOriginalCodePoint) ==
+ CharUtils::toLowerCase(nodeCodePoint)) {
+ // Only cases of the code points are different.
+ return ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
+ } else if (CharUtils::toBaseCodePoint(primaryOriginalCodePoint) ==
+ CharUtils::toBaseCodePoint(nodeCodePoint)) {
+ // Node code point is a variant of original code point.
+ return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR;
+ } else {
+ // Node code point is a variant of original code point and the cases are also
+ // different.
+ return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR
+ | ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
+ }
}
+ break;
case CT_ADDITIONAL_PROXIMITY:
- return ET_PROXIMITY_CORRECTION;
+ return ErrorTypeUtils::PROXIMITY_CORRECTION;
case CT_OMISSION:
if (parentDicNode->canBeIntentionalOmission()) {
- return ET_INTENTIONAL_OMISSION;
+ return ErrorTypeUtils::INTENTIONAL_OMISSION;
} else {
- return ET_EDIT_CORRECTION;
+ return ErrorTypeUtils::EDIT_CORRECTION;
}
break;
case CT_SUBSTITUTION:
case CT_INSERTION:
case CT_TERMINAL_INSERTION:
case CT_TRANSPOSITION:
- return ET_EDIT_CORRECTION;
+ return ErrorTypeUtils::EDIT_CORRECTION;
case CT_NEW_WORD_SPACE_OMISSION:
case CT_NEW_WORD_SPACE_SUBSTITUTION:
- return ET_NEW_WORD;
+ return ErrorTypeUtils::NEW_WORD;
case CT_TERMINAL:
- return ET_NOT_AN_ERROR;
+ return ErrorTypeUtils::NOT_AN_ERROR;
case CT_COMPLETION:
- return ET_COMPLETION;
+ return ErrorTypeUtils::COMPLETION;
default:
- return ET_NOT_AN_ERROR;
+ return ErrorTypeUtils::NOT_AN_ERROR;
}
}
} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 9f0a331e3..41314ef52 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -19,6 +19,7 @@
#include "defines.h"
#include "suggest/core/dicnode/dic_node_utils.h"
+#include "suggest/core/dictionary/error_type_utils.h"
#include "suggest/core/layout/touch_position_correction_utils.h"
#include "suggest/core/policy/weighting.h"
#include "suggest/core/session/dic_traverse_session.h"
@@ -204,7 +205,7 @@ class TypingWeighting : public Weighting {
return cost * traverseSession->getMultiWordCostMultiplier();
}
- ErrorType getErrorType(const CorrectionType correctionType,
+ ErrorTypeUtils::ErrorType getErrorType(const CorrectionType correctionType,
const DicTraverseSession *const traverseSession,
const DicNode *const parentDicNode, const DicNode *const dicNode) const;
diff --git a/native/jni/src/utils/exclusive_ownership_pointer.h b/native/jni/src/utils/exclusive_ownership_pointer.h
new file mode 100644
index 000000000..3cf78954a
--- /dev/null
+++ b/native/jni/src/utils/exclusive_ownership_pointer.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_EXCLUSIVE_OWNERSHIP_POINTER_H
+#define LATINIME_EXCLUSIVE_OWNERSHIP_POINTER_H
+
+#include "defines.h"
+
+namespace latinime {
+
+template<class T>
+class ExclusiveOwnershipPointer {
+ public:
+ // This instance become an owner of the raw pointer.
+ ExclusiveOwnershipPointer(T *const rawPointer)
+ : mPointer(rawPointer),
+ mSharedOwnerPtr(new (ExclusiveOwnershipPointer<T> *)(this)) {}
+
+ // Move the ownership.
+ ExclusiveOwnershipPointer(const ExclusiveOwnershipPointer<T> &pointer)
+ : mPointer(pointer.mPointer), mSharedOwnerPtr(pointer.mSharedOwnerPtr) {
+ transferOwnership(&pointer);
+ }
+
+ ~ExclusiveOwnershipPointer() {
+ deletePointersIfHavingOwnership();
+ }
+
+ // Move the ownership.
+ ExclusiveOwnershipPointer<T> &operator=(const ExclusiveOwnershipPointer<T> &pointer) {
+ // Delete pointers when this is an owner of another pointer.
+ deletePointersIfHavingOwnership();
+ mPointer = pointer.mPointer;
+ mSharedOwnerPtr = pointer.mSharedOwnerPtr;
+ transferOwnership(pointer);
+ return *this;
+ }
+
+ T *get() const {
+ return mPointer;
+ }
+
+ private:
+ // This class allows to copy and assign and ensures only one instance has the ownership of the
+ // managed pointer.
+
+ ExclusiveOwnershipPointer() : mPointer(0), mSharedOwnerPtr(0) {}
+
+ void transferOwnership(const ExclusiveOwnershipPointer<T> *const src) {
+ if (*mSharedOwnerPtr != src) {
+ AKLOGE("Failed to transfer the ownership because src is not the current owner."
+ "src: %p, owner: %p", src, *mSharedOwnerPtr);
+ ASSERT(false);
+ return;
+ }
+ // Transfer the ownership from src to this instance.
+ *mSharedOwnerPtr = this;
+ }
+
+ void deletePointersIfHavingOwnership() {
+ if (mSharedOwnerPtr && *mSharedOwnerPtr == this) {
+ if (mPointer) {
+ if (DEBUG_DICT) {
+ AKLOGI("Releasing pointer: %p", mPointer);
+ }
+ delete mPointer;
+ }
+ delete mSharedOwnerPtr;
+ }
+ }
+
+ T *mPointer;
+ // mSharedOwnerPtr points a shared memory space where the instance which has the ownership is
+ // stored.
+ ExclusiveOwnershipPointer<T> **mSharedOwnerPtr;
+};
+} // namespace latinime
+#endif /* LATINIME_EXCLUSIVE_OWNERSHIP_POINTER_H */
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 6bc8b9dd5..8ad8689d8 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -183,7 +183,7 @@ public class InputLogicTests extends InputTestsBase {
final String[] STRINGS_TO_TYPE =
new String[] { "this ", "a+ ", "\u1F607 ", ".. ", ") ", "( ", "% " };
final String[] EXPECTED_RESULTS =
- new String[] { "this. ", "a+. ", "\u1F607. ", ".. ", "). ", "( ", "% " };
+ new String[] { "this. ", "a+. ", "\u1F607. ", ".. ", "). ", "( ", "%. " };
for (int i = 0; i < STRINGS_TO_TYPE.length; ++i) {
mEditText.setText("");
type(STRINGS_TO_TYPE[i]);
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
index 0189b3334..d670aad43 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
@@ -26,7 +26,6 @@ import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncodin
import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
@@ -60,9 +59,6 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
private static final int NUM_OF_NODES_HAVING_SHORTCUTS = 50;
private static final int NUM_OF_SHORTCUTS = 5;
- private static final int USE_BYTE_ARRAY = 1;
- private static final int USE_BYTE_BUFFER = 2;
-
private static final ArrayList<String> sWords = CollectionUtils.newArrayList();
private static final SparseArray<List<Integer>> sEmptyBigrams =
CollectionUtils.newSparseArray();
@@ -71,18 +67,6 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
CollectionUtils.newSparseArray();
private static final HashMap<String, List<String>> sShortcuts = CollectionUtils.newHashMap();
- private static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2);
- private static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE =
- new FormatSpec.FormatOptions(3, false /* supportsDynamicUpdate */);
- private static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE =
- new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */);
- private static final FormatSpec.FormatOptions VERSION4_WITHOUT_DYNAMIC_UPDATE =
- new FormatSpec.FormatOptions(4, false /* supportsDynamicUpdate */);
- private static final FormatSpec.FormatOptions VERSION4_WITH_DYNAMIC_UPDATE =
- new FormatSpec.FormatOptions(4, true /* supportsDynamicUpdate */);
-
- private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
-
public BinaryDictDecoderEncoderTests() {
this(System.currentTimeMillis(), DEFAULT_MAX_UNIGRAMS);
}
@@ -121,17 +105,6 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
}
- private DictEncoder getDictEncoder(final File file, final FormatOptions formatOptions) {
- if (formatOptions.mVersion == FormatSpec.VERSION4) {
- return new Ver4DictEncoder(getContext().getCacheDir());
- } else if (formatOptions.mVersion == 3 || formatOptions.mVersion == 2) {
- return new Ver3DictEncoder(file);
- } else {
- throw new RuntimeException("The format option has a wrong version : "
- + formatOptions.mVersion);
- }
- }
-
private void generateWords(final int number, final Random random, final int[] codePointSet) {
final Set<String> wordSet = CollectionUtils.newHashSet();
while (wordSet.size() < number) {
@@ -183,7 +156,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
long now = -1, diff = -1;
try {
- final DictEncoder dictEncoder = getDictEncoder(file, formatOptions);
+ final DictEncoder dictEncoder = BinaryDictUtils.getDictEncoder(file, formatOptions,
+ getContext().getCacheDir());
now = System.currentTimeMillis();
// If you need to dump the dict to a textual file, uncomment the line below and the
@@ -238,54 +212,21 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
private String outputOptions(final int bufferType,
final FormatSpec.FormatOptions formatOptions) {
String result = " : buffer type = "
- + ((bufferType == USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
+ + ((bufferType == BinaryDictUtils.USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
result += " : version = " + formatOptions.mVersion;
return result + ", supportsDynamicUpdate = " + formatOptions.mSupportsDynamicUpdate;
}
- private DictionaryOptions getDictionaryOptions(final String id, final String version) {
- final DictionaryOptions options = new DictionaryOptions(new HashMap<String, String>(),
- false, false);
- options.mAttributes.put("version", version);
- options.mAttributes.put("dictionary", id);
- return options;
- }
-
- private File setUpDictionaryFile(final String name, final String version) {
- File file = null;
- try {
- file = new File(getContext().getCacheDir(), name + "." + version
- + TEST_DICT_FILE_EXTENSION);
- file.createNewFile();
- } catch (IOException e) {
- // do nothing
- }
- assertTrue("Failed to create the dictionary file.", file.exists());
- return file;
- }
-
- private DictDecoder getDictDecoder(final File file, final int bufferType,
- final FormatOptions formatOptions, final DictionaryOptions dictOptions) {
- if (formatOptions.mVersion == FormatSpec.VERSION4) {
- final FileHeader header = new FileHeader(0, dictOptions, formatOptions);
- return FormatSpec.getDictDecoder(new File(getContext().getCacheDir(),
- header.getId() + "." + header.getVersion()), bufferType);
- } else {
- return FormatSpec.getDictDecoder(file, bufferType);
- }
- }
// Tests for readDictionaryBinary and writeDictionaryBinary
private long timeReadingAndCheckDict(final File file, final List<String> words,
final SparseArray<List<Integer>> bigrams,
- final HashMap<String, List<String>> shortcutMap, final int bufferType,
- final FormatOptions formatOptions, final DictionaryOptions dictOptions) {
+ final HashMap<String, List<String>> shortcutMap, final int bufferType) {
long now, diff = -1;
FusionDictionary dict = null;
try {
- final DictDecoder dictDecoder = getDictDecoder(file, bufferType, formatOptions,
- dictOptions);
+ final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, bufferType);
now = System.currentTimeMillis();
dict = dictDecoder.readDictionaryBinary(null, false /* deleteDictIfBroken */);
diff = System.currentTimeMillis() - now;
@@ -307,17 +248,17 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final String dictName = "runReadAndWrite";
final String dictVersion = Long.toString(System.currentTimeMillis());
- final File file = setUpDictionaryFile(dictName, dictVersion);
+ final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
+ getContext().getCacheDir());
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- getDictionaryOptions(dictName, dictVersion));
+ BinaryDictUtils.getDictionaryOptions(dictName, dictVersion));
addUnigrams(words.size(), dict, words, shortcuts);
addBigrams(dict, words, bigrams);
checkDictionary(dict, words, bigrams, shortcuts);
final long write = timeWritingDictToFile(file, dict, formatOptions);
- final long read = timeReadingAndCheckDict(file, words, bigrams, shortcuts, bufferType,
- formatOptions, dict.mOptions);
+ final long read = timeReadingAndCheckDict(file, words, bigrams, shortcuts, bufferType);
return "PROF: read=" + read + "ms, write=" + write + "ms :" + message
+ " : " + outputOptions(bufferType, formatOptions);
@@ -346,8 +287,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final byte[] buffer = new byte[50 * 3];
final DictBuffer dictBuffer = new ByteArrayDictBuffer(buffer);
for (final String word : sWords) {
- Log.d("testReadAndWriteString", "write : " + word);
- Arrays.fill(buffer, (byte)0);
+ Arrays.fill(buffer, (byte) 0);
CharEncoding.writeString(buffer, 0, word);
dictBuffer.position(0);
final String str = CharEncoding.readString(dictBuffer);
@@ -358,11 +298,18 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
public void testReadAndWriteWithByteBuffer() {
final List<String> results = CollectionUtils.newArrayList();
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION2);
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION2);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP);
for (final String result : results) {
Log.d(TAG, result);
@@ -372,11 +319,18 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
public void testReadAndWriteWithByteArray() {
final List<String> results = CollectionUtils.newArrayList();
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION2);
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE);
- runReadAndWriteTests(results, USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION2);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP);
for (final String result : results) {
Log.d(TAG, result);
@@ -432,8 +386,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
- final SparseArray<List<Integer>> bigrams, final int bufferType,
- final FormatOptions formatOptions, final DictionaryOptions dictOptions) {
+ final SparseArray<List<Integer>> bigrams, final int bufferType) {
FileInputStream inStream = null;
final TreeMap<Integer, String> resultWords = CollectionUtils.newTreeMap();
@@ -443,8 +396,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
long now = -1, diff = -1;
try {
- final DictDecoder dictDecoder = getDictDecoder(file, bufferType, formatOptions,
- dictOptions);
+ final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, bufferType);
now = System.currentTimeMillis();
dictDecoder.readUnigramsAndBigramsBinary(resultWords, resultFreqs, resultBigrams);
diff = System.currentTimeMillis() - now;
@@ -471,20 +423,20 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final FormatSpec.FormatOptions formatOptions, final String message) {
final String dictName = "runReadUnigrams";
final String dictVersion = Long.toString(System.currentTimeMillis());
- final File file = setUpDictionaryFile(dictName, dictVersion);
+ final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
+ getContext().getCacheDir());
// making the dictionary from lists of words.
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- getDictionaryOptions(dictName, dictVersion));
+ BinaryDictUtils.getDictionaryOptions(dictName, dictVersion));
addUnigrams(words.size(), dict, words, null /* shortcutMap */);
addBigrams(dict, words, bigrams);
timeWritingDictToFile(file, dict, formatOptions);
- long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType,
- formatOptions, dict.mOptions);
+ long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType);
long fullReading = timeReadingAndCheckDict(file, words, bigrams, null /* shortcutMap */,
- bufferType, formatOptions, dict.mOptions);
+ bufferType);
return "readDictionaryBinary=" + fullReading + ", readUnigramsAndBigramsBinary=" + wordMap
+ " : " + message + " : " + outputOptions(bufferType, formatOptions);
@@ -503,11 +455,18 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
public void testReadUnigramsAndBigramsBinaryWithByteBuffer() {
final ArrayList<String> results = CollectionUtils.newArrayList();
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION2);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION2);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP);
for (final String result : results) {
Log.d(TAG, result);
@@ -517,11 +476,18 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
public void testReadUnigramsAndBigramsBinaryWithByteArray() {
final ArrayList<String> results = CollectionUtils.newArrayList();
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION2);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE);
- runReadUnigramsAndBigramsTests(results, USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION2);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
+ runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP);
for (final String result : results) {
Log.d(TAG, result);
@@ -569,16 +535,16 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
final FormatOptions formatOptions, final String message) {
final String dictName = "testGetTerminalPosition";
final String dictVersion = Long.toString(System.currentTimeMillis());
- final File file = setUpDictionaryFile(dictName, dictVersion);
+ final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
+ getContext().getCacheDir());
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- getDictionaryOptions(dictName, dictVersion));
+ BinaryDictUtils.getDictionaryOptions(dictName, dictVersion));
addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
addBigrams(dict, words, bigrams);
timeWritingDictToFile(file, dict, formatOptions);
- final DictDecoder dictDecoder = getDictDecoder(file, DictDecoder.USE_BYTEARRAY,
- formatOptions, dict.mOptions);
+ final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file, DictDecoder.USE_BYTEARRAY);
try {
dictDecoder.openDictBuffer();
} catch (IOException e) {
@@ -629,17 +595,29 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
public void testGetTerminalPosition() {
final ArrayList<String> results = CollectionUtils.newArrayList();
- runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION2);
- runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION3_WITH_DYNAMIC_UPDATE);
- runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION4_WITHOUT_DYNAMIC_UPDATE);
- runGetTerminalPositionTests(USE_BYTE_ARRAY, VERSION4_WITH_DYNAMIC_UPDATE);
-
- runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION2);
- runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION3_WITHOUT_DYNAMIC_UPDATE);
- runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION3_WITH_DYNAMIC_UPDATE);
- runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION4_WITHOUT_DYNAMIC_UPDATE);
- runGetTerminalPositionTests(USE_BYTE_BUFFER, VERSION4_WITH_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY, BinaryDictUtils.VERSION2);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP);
+
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER, BinaryDictUtils.VERSION2);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION3_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITHOUT_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
+ runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
+ BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP);
for (final String result : results) {
Log.d(TAG, result);
@@ -649,7 +627,8 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
private void runTestDeleteWord(final FormatOptions formatOptions) {
final String dictName = "testDeleteWord";
final String dictVersion = Long.toString(System.currentTimeMillis());
- final File file = setUpDictionaryFile(dictName, dictVersion);
+ final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
+ getContext().getCacheDir());
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
new FusionDictionary.DictionaryOptions(
@@ -657,15 +636,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
timeWritingDictToFile(file, dict, formatOptions);
- final DictUpdater dictUpdater;
- if (formatOptions.mVersion == 3) {
- dictUpdater = new Ver3DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
- } else if (formatOptions.mVersion == 4) {
- dictUpdater = new Ver4DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
- } else {
- throw new RuntimeException("DictUpdater for version " + formatOptions.mVersion
- + " doesn't exist.");
- }
+ final DictUpdater dictUpdater = BinaryDictUtils.getDictUpdater(file, formatOptions);
try {
MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD,
@@ -685,7 +656,7 @@ public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
}
public void testDeleteWord() {
- runTestDeleteWord(VERSION3_WITH_DYNAMIC_UPDATE);
- runTestDeleteWord(VERSION4_WITH_DYNAMIC_UPDATE);
+ runTestDeleteWord(BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runTestDeleteWord(BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
index afe5adb73..8bea3c074 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
@@ -23,6 +23,7 @@ import android.util.Log;
import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
+import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
import com.android.inputmethod.latin.utils.CollectionUtils;
@@ -30,24 +31,16 @@ import com.android.inputmethod.latin.utils.CollectionUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Random;
@LargeTest
public class BinaryDictIOUtilsTests extends AndroidTestCase {
private static final String TAG = BinaryDictIOUtilsTests.class.getSimpleName();
- private static final FormatSpec.FormatOptions FORMAT_OPTIONS =
- new FormatSpec.FormatOptions(3, true);
private static final ArrayList<String> sWords = CollectionUtils.newArrayList();
public static final int DEFAULT_MAX_UNIGRAMS = 1500;
private final int mMaxUnigrams;
- private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
-
- private static final int VERSION3 = 3;
- private static final int VERSION4 = 4;
-
private static final String[] CHARACTERS = {
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
@@ -141,7 +134,7 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
int position = FormatSpec.NOT_VALID_WORD;
try {
- final Ver3DictDecoder dictDecoder = new Ver3DictDecoder(file,
+ final DictDecoder dictDecoder = FormatSpec.getDictDecoder(file,
DictDecoder.USE_READONLY_BYTEBUFFER);
position = dictDecoder.getTerminalPosition(word);
} catch (IOException e) {
@@ -159,7 +152,7 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
* @throws IOException
* @throws UnsupportedFormatException
*/
- private static PtNodeInfo findWordByBinaryDictReader(final DictDecoder dictDecoder,
+ private static PtNodeInfo findWordByDictDecoder(final DictDecoder dictDecoder,
final String word) throws IOException, UnsupportedFormatException {
int position = dictDecoder.getTerminalPosition(word);
if (position != FormatSpec.NOT_VALID_WORD) {
@@ -176,7 +169,7 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
PtNodeInfo info = null;
try {
dictDecoder.openDictBuffer();
- info = findWordByBinaryDictReader(dictDecoder, word);
+ info = findWordByDictDecoder(dictDecoder, word);
} catch (IOException e) {
} catch (UnsupportedFormatException e) {
}
@@ -186,16 +179,10 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
// return amount of time to insert a word
private long insertAndCheckWord(final File file, final String word, final int frequency,
final boolean exist, final ArrayList<WeightedString> bigrams,
- final ArrayList<WeightedString> shortcuts, final int formatVersion) {
+ final ArrayList<WeightedString> shortcuts, final FormatOptions formatOptions) {
long amountOfTime = -1;
try {
- final DictUpdater dictUpdater;
- if (formatVersion == VERSION3) {
- dictUpdater = new Ver3DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
- } else {
- throw new RuntimeException("DictUpdater for version " + formatVersion + " doesn't"
- + " exist.");
- }
+ final DictUpdater dictUpdater = BinaryDictUtils.getDictUpdater(file, formatOptions);
if (!exist) {
assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word));
@@ -212,18 +199,14 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
return amountOfTime;
}
- private void deleteWord(final File file, final String word, final int formatVersion) {
+ private void deleteWord(final File file, final String word, final FormatOptions formatOptions) {
try {
- final DictUpdater dictUpdater;
- if (formatVersion == VERSION3) {
- dictUpdater = new Ver3DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
- } else {
- throw new RuntimeException("DictUpdater for version " + formatVersion + " doesn't"
- + " exist.");
- }
+ final DictUpdater dictUpdater = BinaryDictUtils.getDictUpdater(file, formatOptions);
dictUpdater.deleteWord(word);
} catch (IOException e) {
+ Log.e(TAG, "Raised an IOException while deleting a word", e);
} catch (UnsupportedFormatException e) {
+ Log.e(TAG, "Raised an UnsupportedFormatException while deleting a word", e);
}
}
@@ -242,23 +225,21 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
}
}
- private void runTestInsertWord(final int formatVersion) {
- File file = null;
- try {
- file = File.createTempFile("testInsertWord", TEST_DICT_FILE_EXTENSION,
- getContext().getCacheDir());
- } catch (IOException e) {
- fail("IOException while creating temporary file: " + e);
- }
+ private void runTestInsertWord(final FormatOptions formatOptions) {
+ final String testName = "testInsertWord";
+ final String version = Long.toString(System.currentTimeMillis());
+ final File file = BinaryDictUtils.getDictFile(testName, version, formatOptions,
+ getContext().getCacheDir());
// set an initial dictionary.
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false));
+ BinaryDictUtils.getDictionaryOptions(testName, version));
dict.add("abcd", 10, null, false);
try {
- final DictEncoder dictEncoder = new Ver3DictEncoder(file);
- dictEncoder.writeDictionary(dict, FORMAT_OPTIONS);
+ final DictEncoder dictEncoder = BinaryDictUtils.getDictEncoder(file, formatOptions,
+ getContext().getCacheDir());
+ dictEncoder.writeDictionary(dict, formatOptions);
} catch (IOException e) {
fail("IOException while writing an initial dictionary : " + e);
} catch (UnsupportedFormatException e) {
@@ -266,54 +247,68 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
}
MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "abcd"));
- insertAndCheckWord(file, "abcde", 10, false, null, null, formatVersion);
+ insertAndCheckWord(file, "abcde", 10, false, null, null, formatOptions);
+ checkReverseLookup(file, "abcde", getWordPosition(file, "abcde"));
- insertAndCheckWord(file, "abcdefghijklmn", 10, false, null, null, formatVersion);
+ insertAndCheckWord(file, "abcdefghijklmn", 10, false, null, null, formatOptions);
checkReverseLookup(file, "abcdefghijklmn", getWordPosition(file, "abcdefghijklmn"));
- insertAndCheckWord(file, "abcdabcd", 10, false, null, null, formatVersion);
+ insertAndCheckWord(file, "abcdabcd", 10, false, null, null, formatOptions);
checkReverseLookup(file, "abcdabcd", getWordPosition(file, "abcdabcd"));
// update the existing word.
- insertAndCheckWord(file, "abcdabcd", 15, true, null, null, formatVersion);
+ insertAndCheckWord(file, "abcdabcd", 15, true, null, null, formatOptions);
+ checkReverseLookup(file, "abcdabcd", getWordPosition(file, "abcdabcd"));
- // split 1
- insertAndCheckWord(file, "ab", 20, false, null, null, formatVersion);
+ // Testing splitOnly
+ insertAndCheckWord(file, "ab", 20, false, null, null, formatOptions);
+ checkReverseLookup(file, "ab", getWordPosition(file, "ab"));
+ checkReverseLookup(file, "abcdabcd", getWordPosition(file, "abcdabcd"));
+ checkReverseLookup(file, "abcde", getWordPosition(file, "abcde"));
+ checkReverseLookup(file, "abcdefghijklmn", getWordPosition(file, "abcdefghijklmn"));
- // split 2
- insertAndCheckWord(file, "ami", 30, false, null, null, formatVersion);
+ // Testing splitAndBranch
+ insertAndCheckWord(file, "ami", 30, false, null, null, formatOptions);
+ checkReverseLookup(file, "ami", getWordPosition(file, "ami"));
+ checkReverseLookup(file, "ab", getWordPosition(file, "ab"));
+ checkReverseLookup(file, "abcdabcd", getWordPosition(file, "abcdabcd"));
+ checkReverseLookup(file, "abcde", getWordPosition(file, "abcde"));
+ checkReverseLookup(file, "abcdefghijklmn", getWordPosition(file, "abcdefghijklmn"));
+ checkReverseLookup(file, "ami", getWordPosition(file, "ami"));
+
+ insertAndCheckWord(file, "abcdefzzzz", 40, false, null, null, formatOptions);
+ checkReverseLookup(file, "abcdefzzzz", getWordPosition(file, "abcdefzzzz"));
- deleteWord(file, "ami", formatVersion);
+ deleteWord(file, "ami", formatOptions);
assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "ami"));
- insertAndCheckWord(file, "abcdabfg", 30, false, null, null, formatVersion);
+ insertAndCheckWord(file, "abcdabfg", 30, false, null, null, formatOptions);
- deleteWord(file, "abcd", formatVersion);
+ deleteWord(file, "abcd", formatOptions);
assertEquals(FormatSpec.NOT_VALID_WORD, getWordPosition(file, "abcd"));
}
public void testInsertWord() {
- runTestInsertWord(VERSION3);
+ runTestInsertWord(BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runTestInsertWord(BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
}
- private void runTestInsertWordWithBigrams(final int formatVersion) {
- File file = null;
- try {
- file = File.createTempFile("testInsertWordWithBigrams", TEST_DICT_FILE_EXTENSION,
- getContext().getCacheDir());
- } catch (IOException e) {
- fail("IOException while creating temporary file: " + e);
- }
+ private void runTestInsertWordWithBigrams(final FormatOptions formatOptions) {
+ final String testName = "testInsertWordWithBigrams";
+ final String version = Long.toString(System.currentTimeMillis());
+ File file = BinaryDictUtils.getDictFile(testName, version, formatOptions,
+ getContext().getCacheDir());
// set an initial dictionary.
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- new FusionDictionary.DictionaryOptions(new HashMap<String,String>(), false, false));
+ BinaryDictUtils.getDictionaryOptions(testName, version));
dict.add("abcd", 10, null, false);
dict.add("efgh", 15, null, false);
try {
- final DictEncoder dictEncoder = new Ver3DictEncoder(file);
- dictEncoder.writeDictionary(dict, FORMAT_OPTIONS);
+ final DictEncoder dictEncoder = BinaryDictUtils.getDictEncoder(file, formatOptions,
+ getContext().getCacheDir());
+ dictEncoder.writeDictionary(dict, formatOptions);
} catch (IOException e) {
fail("IOException while writing an initial dictionary : " + e);
} catch (UnsupportedFormatException e) {
@@ -323,8 +318,8 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
final ArrayList<WeightedString> banana = new ArrayList<WeightedString>();
banana.add(new WeightedString("banana", 10));
- insertAndCheckWord(file, "banana", 0, false, null, null, formatVersion);
- insertAndCheckWord(file, "recursive", 60, true, banana, null, formatVersion);
+ insertAndCheckWord(file, "banana", 0, false, null, null, formatOptions);
+ insertAndCheckWord(file, "recursive", 60, true, banana, null, formatOptions);
final PtNodeInfo info = findWordFromFile(file, "recursive");
int bananaPos = getWordPosition(file, "banana");
@@ -334,27 +329,25 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
}
public void testInsertWordWithBigrams() {
- runTestInsertWordWithBigrams(VERSION3);
+ runTestInsertWordWithBigrams(BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runTestInsertWordWithBigrams(BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
}
- private void runTestRandomWords(final int formatVersion) {
- File file = null;
- try {
- file = File.createTempFile("testRandomWord", TEST_DICT_FILE_EXTENSION,
- getContext().getCacheDir());
- } catch (IOException e) {
- }
- assertNotNull(file);
+ private void runTestRandomWords(final FormatOptions formatOptions) {
+ final String testName = "testRandomWord";
+ final String version = Long.toString(System.currentTimeMillis());
+ final File file = BinaryDictUtils.getDictFile(testName, version, formatOptions,
+ getContext().getCacheDir());
// set an initial dictionary.
final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
- new FusionDictionary.DictionaryOptions(new HashMap<String, String>(), false,
- false));
+ BinaryDictUtils.getDictionaryOptions(testName, version));
dict.add("initial", 10, null, false);
try {
- final DictEncoder dictEncoder = new Ver3DictEncoder(file);
- dictEncoder.writeDictionary(dict, FORMAT_OPTIONS);
+ final DictEncoder dictEncoder = BinaryDictUtils.getDictEncoder(file, formatOptions,
+ getContext().getCacheDir());
+ dictEncoder.writeDictionary(dict, formatOptions);
} catch (IOException e) {
assertTrue(false);
} catch (UnsupportedFormatException e) {
@@ -366,7 +359,7 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
int cnt = 0;
for (final String word : sWords) {
final long diff = insertAndCheckWord(file, word,
- cnt % FormatSpec.MAX_TERMINAL_FREQUENCY, false, null, null, formatVersion);
+ cnt % FormatSpec.MAX_TERMINAL_FREQUENCY, false, null, null, formatOptions);
maxTimeToInsert = Math.max(maxTimeToInsert, diff);
minTimeToInsert = Math.min(minTimeToInsert, diff);
sum += diff;
@@ -377,13 +370,14 @@ public class BinaryDictIOUtilsTests extends AndroidTestCase {
MoreAsserts.assertNotEqual(FormatSpec.NOT_VALID_WORD, getWordPosition(file, word));
}
- Log.d(TAG, "Test version " + formatVersion);
+ Log.d(TAG, "Test version " + formatOptions.mVersion);
Log.d(TAG, "max = " + ((double)maxTimeToInsert/1000000) + " ms.");
Log.d(TAG, "min = " + ((double)minTimeToInsert/1000000) + " ms.");
Log.d(TAG, "avg = " + ((double)sum/mMaxUnigrams/1000000) + " ms.");
}
public void testRandomWords() {
- runTestRandomWords(VERSION3);
+ runTestRandomWords(BinaryDictUtils.VERSION3_WITH_DYNAMIC_UPDATE);
+ runTestRandomWords(BinaryDictUtils.VERSION4_WITH_DYNAMIC_UPDATE);
}
}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
new file mode 100644
index 000000000..f476738f3
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.makedict;
+
+import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
+import com.android.inputmethod.latin.makedict.FusionDictionary.DictionaryOptions;
+
+import java.io.File;
+import java.util.HashMap;
+
+public class BinaryDictUtils {
+ public static final int USE_BYTE_ARRAY = 1;
+ public static final int USE_BYTE_BUFFER = 2;
+
+ public static final String TEST_DICT_FILE_EXTENSION = ".testDict";
+
+ public static final FormatSpec.FormatOptions VERSION2 = new FormatSpec.FormatOptions(2);
+ public static final FormatSpec.FormatOptions VERSION3_WITHOUT_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(3, false /* supportsDynamicUpdate */);
+ public static final FormatSpec.FormatOptions VERSION3_WITH_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(3, true /* supportsDynamicUpdate */);
+ public static final FormatSpec.FormatOptions VERSION4_WITHOUT_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(4, false /* supportsDynamicUpdate */);
+ public static final FormatSpec.FormatOptions VERSION4_WITH_DYNAMIC_UPDATE =
+ new FormatSpec.FormatOptions(4, true /* supportsDynamicUpdate */);
+ public static final FormatSpec.FormatOptions VERSION4_WITH_DYNAMIC_UPDATE_AND_TIMESTAMP =
+ new FormatSpec.FormatOptions(4, true /* supportsDynamicUpdate */,
+ true /* hasTimestamp */);
+
+ public static DictionaryOptions getDictionaryOptions(final String id, final String version) {
+ final DictionaryOptions options = new DictionaryOptions(new HashMap<String, String>(),
+ false /* germanUmlautProcessing */, false /* frenchLigatureProcessing */);
+ options.mAttributes.put("dictionary", id);
+ options.mAttributes.put("version", version);
+ return options;
+ }
+
+ public static File getDictFile(final String name, final String version,
+ final FormatOptions formatOptions, final File directory) {
+ if (formatOptions.mVersion == 2 || formatOptions.mVersion == 3) {
+ return new File(directory, name + "." + version + TEST_DICT_FILE_EXTENSION);
+ } else if (formatOptions.mVersion == 4) {
+ return new File(directory, name + "." + version);
+ } else {
+ throw new RuntimeException("the format option has a wrong version : "
+ + formatOptions.mVersion);
+ }
+ }
+
+ public static DictEncoder getDictEncoder(final File file, final FormatOptions formatOptions,
+ final File cacheDir) {
+ if (formatOptions.mVersion == FormatSpec.VERSION4) {
+ return new Ver4DictEncoder(cacheDir);
+ } else if (formatOptions.mVersion == 3 || formatOptions.mVersion == 2) {
+ return new Ver3DictEncoder(file);
+ } else {
+ throw new RuntimeException("The format option has a wrong version : "
+ + formatOptions.mVersion);
+ }
+ }
+
+ public static DictUpdater getDictUpdater(final File file, final FormatOptions formatOptions) {
+ if (formatOptions.mVersion == FormatSpec.VERSION4) {
+ return new Ver4DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
+ } else if (formatOptions.mVersion == 3) {
+ return new Ver3DictUpdater(file, DictDecoder.USE_WRITABLE_BYTEBUFFER);
+ } else {
+ throw new RuntimeException("The format option has a wrong version : "
+ + formatOptions.mVersion);
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
index 856b2dbda..ccdd56750 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
@@ -41,7 +41,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
InputMethodSubtype ES_US;
InputMethodSubtype FR;
InputMethodSubtype FR_CA;
+ InputMethodSubtype FR_CH;
InputMethodSubtype DE;
+ InputMethodSubtype DE_CH;
InputMethodSubtype ZZ;
InputMethodSubtype DE_QWERTY;
InputMethodSubtype FR_QWERTZ;
@@ -70,8 +72,12 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
Locale.FRENCH.toString(), "azerty");
FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
Locale.CANADA_FRENCH.toString(), "qwerty");
+ FR_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "fr_CH", "swiss");
DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
Locale.GERMAN.toString(), "qwertz");
+ DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+ "de_CH", "swiss");
ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
DE_QWERTY = AdditionalSubtypeUtils.createAdditionalSubtype(
@@ -112,7 +118,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
assertEquals("es_US", "spanish", SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US));
assertEquals("fr ", "azerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR));
assertEquals("fr_CA", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CA));
+ assertEquals("fr_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CH));
assertEquals("de ", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE));
+ assertEquals("de_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_CH));
assertEquals("zz ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ));
}
@@ -125,7 +133,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
// es_US spanish F Spanish (US) exception
// fr azerty F French
// fr_CA qwerty F French (Canada)
+ // fr_CH swiss F French (Switzerland)
// de qwertz F German
+ // de_CH swiss F German (Switzerland)
// zz qwerty F Alphabet (QWERTY)
// fr qwertz T French (QWERTZ)
// de qwerty T German (QWERTY)
@@ -148,8 +158,12 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR));
assertEquals("fr_CA", "French (Canada)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA));
+ assertEquals("fr_CH", "French (Switzerland)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH));
assertEquals("de ", "German",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
+ assertEquals("de_CH", "German (Switzerland)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
assertEquals("zz ", "Alphabet (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
return null;
@@ -189,7 +203,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
// es_US spanish F Espagnol (États-Unis) exception
// fr azerty F Français
// fr_CA qwerty F Français (Canada)
+ // fr_CH swiss F Français (Suisse)
// de qwertz F Allemand
+ // de_CH swiss F Allemand (Suisse)
// zz qwerty F Aucune langue (QWERTY)
// fr qwertz T Français (QWERTZ)
// de qwerty T Allemand (QWERTY)
@@ -212,8 +228,12 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR));
assertEquals("fr_CA", "Français (Canada)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA));
+ assertEquals("fr_CH", "Français (Suisse)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH));
assertEquals("de ", "Allemand",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
+ assertEquals("de_CH", "Allemand (Suisse)",
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
assertEquals("zz ", "Alphabet latin (QWERTY)",
SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
return null;
@@ -300,7 +320,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
// es_US spanish F Es Español Español (EE.UU.) exception
// fr azerty F Fr Français Français
// fr_CA qwerty F Fr Français Français (Canada)
+ // fr_CH swiss F Fr Français Français (Suisse)
// de qwertz F De Deutsch Deutsch
+ // de_CH swiss F De Deutsch Deutsch (Schweiz)
// zz qwerty F QWERTY QWERTY
// fr qwertz T Fr Français Français
// de qwerty T De Deutsch Deutsch
@@ -317,7 +339,11 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
assertEquals("fr ", "Français", SubtypeLocaleUtils.getFullDisplayName(FR));
assertEquals("fr_CA", "Français (Canada)",
SubtypeLocaleUtils.getFullDisplayName(FR_CA));
+ assertEquals("fr_CH", "Français (Suisse)",
+ SubtypeLocaleUtils.getFullDisplayName(FR_CH));
assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getFullDisplayName(DE));
+ assertEquals("de_CH", "Deutsch (Schweiz)",
+ SubtypeLocaleUtils.getFullDisplayName(DE_CH));
assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getFullDisplayName(ZZ));
assertEquals("en_US", "English", SubtypeLocaleUtils.getMiddleDisplayName(EN_US));
@@ -325,7 +351,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
assertEquals("es_US", "Español", SubtypeLocaleUtils.getMiddleDisplayName(ES_US));
assertEquals("fr ", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR));
assertEquals("fr_CA", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR_CA));
+ assertEquals("fr_CH", "Français", SubtypeLocaleUtils.getMiddleDisplayName(FR_CH));
assertEquals("de ", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE));
+ assertEquals("de_CH", "Deutsch", SubtypeLocaleUtils.getMiddleDisplayName(DE_CH));
assertEquals("zz ", "QWERTY", SubtypeLocaleUtils.getMiddleDisplayName(ZZ));
assertEquals("en_US", "En", SubtypeLocaleUtils.getShortDisplayName(EN_US));
@@ -333,7 +361,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
assertEquals("es_US", "Es", SubtypeLocaleUtils.getShortDisplayName(ES_US));
assertEquals("fr ", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR));
assertEquals("fr_CA", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR_CA));
+ assertEquals("fr_CH", "Fr", SubtypeLocaleUtils.getShortDisplayName(FR_CH));
assertEquals("de ", "De", SubtypeLocaleUtils.getShortDisplayName(DE));
+ assertEquals("de_CH", "De", SubtypeLocaleUtils.getShortDisplayName(DE_CH));
assertEquals("zz ", "", SubtypeLocaleUtils.getShortDisplayName(ZZ));
return null;
}
diff --git a/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml
index 9dc8717ec..bb8bb7201 100644
--- a/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-de/donottranslate-more-keys.xml
@@ -55,6 +55,18 @@
<!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE -->
<string name="more_keys_for_n">&#x00F1;,&#x0144;</string>
+ <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS -->
+ <string name="keylabel_for_swiss_row1_11">&#x00FC;</string>
+ <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE -->
+ <string name="more_keys_for_swiss_row1_11">&#x00E8;</string>
+ <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS -->
+ <string name="keylabel_for_swiss_row2_10">&#x00F6;</string>
+ <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE -->
+ <string name="more_keys_for_swiss_row2_10">&#x00E9;</string>
+ <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS -->
+ <string name="keylabel_for_swiss_row2_11">&#x00E4;</string>
+ <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE -->
+ <string name="more_keys_for_swiss_row2_11">&#x00E0;</string>
<string name="single_quotes">!text/single_9qm_lqm</string>
<string name="double_quotes">!text/double_9qm_lqm</string>
<string name="single_angle_quotes">!text/single_raqm_laqm</string>
diff --git a/tools/make-keyboard-text/res/values-fr/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-fr/donottranslate-more-keys.xml
index 7b11a183d..665677698 100644
--- a/tools/make-keyboard-text/res/values-fr/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-fr/donottranslate-more-keys.xml
@@ -65,4 +65,16 @@
<string name="more_keys_for_c">&#x00E7;,&#x0107;,&#x010D;</string>
<!-- U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS -->
<string name="more_keys_for_y">%,&#x00FF;</string>
+ <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE -->
+ <string name="keylabel_for_swiss_row1_11">&#x00E8;</string>
+ <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS -->
+ <string name="more_keys_for_swiss_row1_11">&#x00FC;</string>
+ <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE -->
+ <string name="keylabel_for_swiss_row2_10">&#x00E9;</string>
+ <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS -->
+ <string name="more_keys_for_swiss_row2_10">&#x00F6;</string>
+ <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE -->
+ <string name="keylabel_for_swiss_row2_11">&#x00E0;</string>
+ <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS -->
+ <string name="more_keys_for_swiss_row2_11">&#x00E4;</string>
</resources>
diff --git a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
index 64396b1dd..008ef3007 100644
--- a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
@@ -63,6 +63,12 @@
<string name="keylabel_for_south_slavic_row3_8"></string>
<string name="more_keys_for_cyrillic_ie"></string>
<string name="more_keys_for_cyrillic_i"></string>
+ <string name="keylabel_for_swiss_row1_11"></string>
+ <string name="keylabel_for_swiss_row2_10"></string>
+ <string name="keylabel_for_swiss_row2_11"></string>
+ <string name="more_keys_for_swiss_row1_11"></string>
+ <string name="more_keys_for_swiss_row2_10"></string>
+ <string name="more_keys_for_swiss_row2_11"></string>
<!-- Label for "switch to alphabetic" key. -->
<string name="label_to_alpha_key">ABC</string>
<string name="single_quotes">!text/single_lqm_rqm</string>