diff options
467 files changed, 13926 insertions, 5400 deletions
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml index 031d62e0c..a8dabd274 100644 --- a/java/AndroidManifest.xml +++ b/java/AndroidManifest.xml @@ -18,7 +18,7 @@ coreApp="true" package="com.android.inputmethod.latin"> - <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> + <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> diff --git a/java/res/color/emoji_tab_label_color_ics.xml b/java/res/color/emoji_tab_label_color_holo.xml index 36e1d3020..373e9314b 100644 --- a/java/res/color/emoji_tab_label_color_ics.xml +++ b/java/res/color/emoji_tab_label_color_holo.xml @@ -21,13 +21,13 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" - android:color="@color/key_text_color_ics" /> + android:color="@color/key_text_color_holo" /> <item android:state_pressed="true" - android:color="@color/key_text_color_ics" /> + android:color="@color/key_text_color_holo" /> <item android:state_selected="true" - android:color="@color/key_text_color_ics" /> + android:color="@color/key_text_color_holo" /> <item - android:color="@color/key_text_inactivated_color_ics" /> + android:color="@color/key_text_inactivated_color_holo" /> </selector> diff --git a/java/res/color/key_text_color_ics.xml b/java/res/color/key_text_color_holo.xml index c6f111ad2..d034a945f 100644 --- a/java/res/color/key_text_color_ics.xml +++ b/java/res/color/key_text_color_holo.xml @@ -17,32 +17,32 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Functional keys. --> <item android:state_single="true" android:state_pressed="true" - android:color="@color/key_text_color_functional_ics" /> + android:color="@color/key_text_color_functional_holo" /> <item android:state_single="true" - android:color="@color/key_text_color_functional_ics" /> + android:color="@color/key_text_color_functional_holo" /> <!-- Action keys. --> <item android:state_active="true" android:state_pressed="true" - android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> <item android:state_active="true" - android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> <!-- Toggle keys. Use checkable/checked state. --> <item android:state_checkable="true" android:state_checked="true" android:state_pressed="true" - android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> <item android:state_checkable="true" android:state_pressed="true" - android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> <item android:state_checkable="true" android:state_checked="true" - android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> <item android:state_checkable="true" - android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> <!-- Empty background keys. --> <item android:state_empty="true" - android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> <!-- Normal keys. --> <item android:state_pressed="true" - android:color="@color/key_text_color_normal_ics" /> - <item android:color="@color/key_text_color_normal_ics" /> + android:color="@color/key_text_color_normal_holo" /> + <item android:color="@color/key_text_color_normal_holo" /> </selector> diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_active_ics.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_active_ics.9.png Binary files differnew file mode 100644 index 000000000..9aa8db60e --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_active_ics.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_active_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_active_klp.9.png Binary files differindex fa2cb8542..fa2cb8542 100644 --- a/java/res/drawable-hdpi/btn_keyboard_key_dark_active_holo.9.png +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_active_klp.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_ics.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_ics.9.png Binary files differnew file mode 100644 index 000000000..9f4587b4a --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_ics.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_klp.9.png Binary files differindex 814e40235..814e40235 100644 --- a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_holo.9.png +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on_klp.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_ics.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..7ec33dd20 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_ics.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_klp.9.png Binary files differindex 90abe3940..90abe3940 100644 --- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_holo.9.png +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_klp.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_ics.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_ics.9.png Binary files differnew file mode 100644 index 000000000..655bc01b1 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_ics.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_klp.9.png Binary files differindex 48eeb3f54..48eeb3f54 100644 --- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_holo.9.png +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off_klp.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_ics.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_ics.9.png Binary files differnew file mode 100644 index 000000000..138e915d9 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_ics.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_klp.9.png Binary files differindex 71e0683cd..71e0683cd 100644 --- a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_holo.9.png +++ b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on_klp.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_ics.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..5612c51a1 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_ics.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_klp.9.png Binary files differindex 6768241a7..6768241a7 100644 --- a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_holo.9.png +++ b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed_klp.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_ics.9.png b/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_ics.9.png Binary files differnew file mode 100644 index 000000000..c2e8b3779 --- /dev/null +++ b/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_ics.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_klp.9.png Binary files differindex 10f8e97e4..10f8e97e4 100644 --- a/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_holo.9.png +++ b/java/res/drawable-hdpi/btn_keyboard_key_popup_selected_klp.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background_ics.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background_ics.9.png Binary files differnew file mode 100644 index 000000000..28b406a5c --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_key_feedback_background_ics.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background_holo.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex 50ed568ff..50ed568ff 100644 --- a/java/res/drawable-hdpi/keyboard_key_feedback_background_holo.9.png +++ b/java/res/drawable-hdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_left_background_ics.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_left_background_ics.9.png Binary files differnew file mode 100644 index 000000000..e42cd88dc --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_key_feedback_left_background_ics.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_left_background_holo.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_left_background_klp.9.png Binary files differindex 9fa6d0003..9fa6d0003 100644 --- a/java/res/drawable-hdpi/keyboard_key_feedback_left_background_holo.9.png +++ b/java/res/drawable-hdpi/keyboard_key_feedback_left_background_klp.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_ics.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..160344073 --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_ics.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_holo.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_klp.9.png Binary files differindex c73269b7e..c73269b7e 100644 --- a/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_holo.9.png +++ b/java/res/drawable-hdpi/keyboard_key_feedback_left_more_background_klp.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_ics.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..a40d4277c --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_ics.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_holo.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_klp.9.png Binary files differindex fffd4021e..fffd4021e 100644 --- a/java/res/drawable-hdpi/keyboard_key_feedback_more_background_holo.9.png +++ b/java/res/drawable-hdpi/keyboard_key_feedback_more_background_klp.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_right_background_ics.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_right_background_ics.9.png Binary files differnew file mode 100644 index 000000000..1f6807376 --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_key_feedback_right_background_ics.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_right_background_holo.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_right_background_klp.9.png Binary files differindex 61c23c19b..61c23c19b 100644 --- a/java/res/drawable-hdpi/keyboard_key_feedback_right_background_holo.9.png +++ b/java/res/drawable-hdpi/keyboard_key_feedback_right_background_klp.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_ics.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..ec53593d9 --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_ics.9.png diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_holo.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_klp.9.png Binary files differindex 827d74363..827d74363 100644 --- a/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_holo.9.png +++ b/java/res/drawable-hdpi/keyboard_key_feedback_right_more_background_klp.9.png diff --git a/java/res/drawable-hdpi/keyboard_popup_panel_background_holo.9.png b/java/res/drawable-hdpi/keyboard_popup_panel_background_holo.9.png Binary files differdeleted file mode 100644 index dc2fc7dfc..000000000 --- a/java/res/drawable-hdpi/keyboard_popup_panel_background_holo.9.png +++ /dev/null diff --git a/java/res/drawable-hdpi/keyboard_popup_panel_background_ics.9.png b/java/res/drawable-hdpi/keyboard_popup_panel_background_ics.9.png Binary files differnew file mode 100644 index 000000000..53d7b6fb3 --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_popup_panel_background_ics.9.png diff --git a/java/res/drawable-hdpi/keyboard_popup_panel_background_klp.9.png b/java/res/drawable-hdpi/keyboard_popup_panel_background_klp.9.png Binary files differnew file mode 100644 index 000000000..f9dd3b8b1 --- /dev/null +++ b/java/res/drawable-hdpi/keyboard_popup_panel_background_klp.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_active_ics.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_active_ics.9.png Binary files differnew file mode 100644 index 000000000..e810c7789 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_active_ics.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_active_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_active_klp.9.png Binary files differindex 8e9a34957..8e9a34957 100644 --- a/java/res/drawable-mdpi/btn_keyboard_key_dark_active_holo.9.png +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_active_klp.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_ics.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_ics.9.png Binary files differnew file mode 100644 index 000000000..f3fc64114 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_ics.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_klp.9.png Binary files differindex b7b2dca43..b7b2dca43 100644 --- a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_holo.9.png +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on_klp.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_ics.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..8f340d355 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_ics.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_klp.9.png Binary files differindex 4a92b80dd..4a92b80dd 100644 --- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_holo.9.png +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_klp.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_ics.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_ics.9.png Binary files differnew file mode 100644 index 000000000..53ea5f894 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_ics.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_klp.9.png Binary files differindex 72125a065..72125a065 100644 --- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_holo.9.png +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off_klp.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_ics.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_ics.9.png Binary files differnew file mode 100644 index 000000000..69c84e7ec --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_ics.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_klp.9.png Binary files differindex 82413d4cc..82413d4cc 100644 --- a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_holo.9.png +++ b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on_klp.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_ics.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..c39dd4a94 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_ics.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_klp.9.png Binary files differindex 049385984..049385984 100644 --- a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_holo.9.png +++ b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed_klp.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_ics.9.png b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_ics.9.png Binary files differnew file mode 100644 index 000000000..93a6e7921 --- /dev/null +++ b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_ics.9.png diff --git a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_klp.9.png Binary files differindex ee0aae28b..ee0aae28b 100644 --- a/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_holo.9.png +++ b/java/res/drawable-mdpi/btn_keyboard_key_popup_selected_klp.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_background_ics.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background_ics.9.png Binary files differnew file mode 100644 index 000000000..7a9f640d1 --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_key_feedback_background_ics.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex 564f5460c..564f5460c 100644 --- a/java/res/drawable-mdpi/keyboard_key_feedback_background_holo.9.png +++ b/java/res/drawable-mdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_left_background_ics.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_left_background_ics.9.png Binary files differnew file mode 100644 index 000000000..5b06f09bb --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_key_feedback_left_background_ics.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_left_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_left_background_klp.9.png Binary files differindex 427c87061..427c87061 100644 --- a/java/res/drawable-mdpi/keyboard_key_feedback_left_background_holo.9.png +++ b/java/res/drawable-mdpi/keyboard_key_feedback_left_background_klp.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_ics.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..fd992d6f4 --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_ics.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_klp.9.png Binary files differindex ea757296d..ea757296d 100644 --- a/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_holo.9.png +++ b/java/res/drawable-mdpi/keyboard_key_feedback_left_more_background_klp.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_ics.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..128dcd6ad --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_ics.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_klp.9.png Binary files differindex 1911c429f..1911c429f 100644 --- a/java/res/drawable-mdpi/keyboard_key_feedback_more_background_holo.9.png +++ b/java/res/drawable-mdpi/keyboard_key_feedback_more_background_klp.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_right_background_ics.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_right_background_ics.9.png Binary files differnew file mode 100644 index 000000000..0b08d1747 --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_key_feedback_right_background_ics.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_right_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_right_background_klp.9.png Binary files differindex cdef116d2..cdef116d2 100644 --- a/java/res/drawable-mdpi/keyboard_key_feedback_right_background_holo.9.png +++ b/java/res/drawable-mdpi/keyboard_key_feedback_right_background_klp.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_ics.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..cf0b33c1d --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_ics.9.png diff --git a/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_holo.9.png b/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_klp.9.png Binary files differindex dea5d076c..dea5d076c 100644 --- a/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_holo.9.png +++ b/java/res/drawable-mdpi/keyboard_key_feedback_right_more_background_klp.9.png diff --git a/java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.png b/java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.png Binary files differdeleted file mode 100644 index 441edc30b..000000000 --- a/java/res/drawable-mdpi/keyboard_popup_panel_background_holo.9.png +++ /dev/null diff --git a/java/res/drawable-mdpi/keyboard_popup_panel_background_ics.9.png b/java/res/drawable-mdpi/keyboard_popup_panel_background_ics.9.png Binary files differnew file mode 100644 index 000000000..61988a8e1 --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_popup_panel_background_ics.9.png diff --git a/java/res/drawable-mdpi/keyboard_popup_panel_background_klp.9.png b/java/res/drawable-mdpi/keyboard_popup_panel_background_klp.9.png Binary files differnew file mode 100644 index 000000000..896505518 --- /dev/null +++ b/java/res/drawable-mdpi/keyboard_popup_panel_background_klp.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_ics.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_ics.9.png Binary files differnew file mode 100644 index 000000000..d990c0258 --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_ics.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_klp.9.png Binary files differindex a2f6ac0e2..a2f6ac0e2 100644 --- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_holo.9.png +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_active_klp.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_ics.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_ics.9.png Binary files differnew file mode 100644 index 000000000..ab8fb2e86 --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_ics.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_klp.9.png Binary files differindex 20251a000..20251a000 100644 --- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_holo.9.png +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_normal_on_klp.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_ics.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..3871689ef --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_ics.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_klp.9.png Binary files differindex 84d173967..84d173967 100644 --- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_holo.9.png +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_klp.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_ics.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_ics.9.png Binary files differnew file mode 100644 index 000000000..912506368 --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_ics.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_klp.9.png Binary files differindex ee4490eac..ee4490eac 100644 --- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_off_klp.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_ics.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_ics.9.png Binary files differnew file mode 100644 index 000000000..35ce67fdc --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_ics.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_klp.9.png Binary files differindex e8124776c..e8124776c 100644 --- a/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png +++ b/java/res/drawable-xhdpi/btn_keyboard_key_dark_pressed_on_klp.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_ics.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..c23a4b225 --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_ics.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_klp.9.png Binary files differindex f770962c3..f770962c3 100644 --- a/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_holo.9.png +++ b/java/res/drawable-xhdpi/btn_keyboard_key_light_pressed_klp.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_ics.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_ics.9.png Binary files differnew file mode 100644 index 000000000..0c7bfdace --- /dev/null +++ b/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_ics.9.png diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_klp.9.png Binary files differindex 891d00024..891d00024 100644 --- a/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_holo.9.png +++ b/java/res/drawable-xhdpi/btn_keyboard_key_popup_selected_klp.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_background_ics.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background_ics.9.png Binary files differnew file mode 100644 index 000000000..d999127f2 --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background_ics.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex e8c65f677..e8c65f677 100644 --- a/java/res/drawable-xhdpi/keyboard_key_feedback_background_holo.9.png +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_ics.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_ics.9.png Binary files differnew file mode 100644 index 000000000..c4d694136 --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_ics.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_klp.9.png Binary files differindex 543bc763e..543bc763e 100644 --- a/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_holo.9.png +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_left_background_klp.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_ics.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..5429c1785 --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_ics.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_klp.9.png Binary files differindex ec42aadb6..ec42aadb6 100644 --- a/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_holo.9.png +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_left_more_background_klp.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_ics.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..5135a0869 --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_ics.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_klp.9.png Binary files differindex 319e9d7cf..319e9d7cf 100644 --- a/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_holo.9.png +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_more_background_klp.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_ics.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_ics.9.png Binary files differnew file mode 100644 index 000000000..19a77a29f --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_ics.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_klp.9.png Binary files differindex 052032be7..052032be7 100644 --- a/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_holo.9.png +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_right_background_klp.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_ics.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..ae2ffff8e --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_ics.9.png diff --git a/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_klp.9.png Binary files differindex c7e9d1c9e..c7e9d1c9e 100644 --- a/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_holo.9.png +++ b/java/res/drawable-xhdpi/keyboard_key_feedback_right_more_background_klp.9.png diff --git a/java/res/drawable-xhdpi/keyboard_popup_panel_background_holo.9.png b/java/res/drawable-xhdpi/keyboard_popup_panel_background_holo.9.png Binary files differdeleted file mode 100644 index dde1856e3..000000000 --- a/java/res/drawable-xhdpi/keyboard_popup_panel_background_holo.9.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/keyboard_popup_panel_background_ics.9.png b/java/res/drawable-xhdpi/keyboard_popup_panel_background_ics.9.png Binary files differnew file mode 100644 index 000000000..1dee699f4 --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_popup_panel_background_ics.9.png diff --git a/java/res/drawable-xhdpi/keyboard_popup_panel_background_klp.9.png b/java/res/drawable-xhdpi/keyboard_popup_panel_background_klp.9.png Binary files differnew file mode 100644 index 000000000..36df715b6 --- /dev/null +++ b/java/res/drawable-xhdpi/keyboard_popup_panel_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_active_ics.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_active_ics.9.png Binary files differnew file mode 100644 index 000000000..680421eaf --- /dev/null +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_active_ics.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_active_holo.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_active_klp.9.png Binary files differindex 17f0a7a58..17f0a7a58 100644 --- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_active_holo.9.png +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_active_klp.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_ics.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_ics.9.png Binary files differnew file mode 100644 index 000000000..40f5011c0 --- /dev/null +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_ics.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_holo.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_klp.9.png Binary files differindex 97f96258e..97f96258e 100644 --- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_holo.9.png +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_normal_on_klp.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_ics.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..6ff6319d3 --- /dev/null +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_ics.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_holo.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_klp.9.png Binary files differindex dfb16a76b..dfb16a76b 100644 --- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_holo.9.png +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_klp.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_ics.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_ics.9.png Binary files differnew file mode 100644 index 000000000..818ea70fd --- /dev/null +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_ics.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_klp.9.png Binary files differindex bf1d34686..bf1d34686 100644 --- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_holo.9.png +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_off_klp.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_ics.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_ics.9.png Binary files differnew file mode 100644 index 000000000..a476d2a9e --- /dev/null +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_ics.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_klp.9.png Binary files differindex 962277165..962277165 100644 --- a/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_holo.9.png +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_dark_pressed_on_klp.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_ics.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_ics.9.png Binary files differnew file mode 100644 index 000000000..3c17c5eec --- /dev/null +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_ics.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_holo.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_klp.9.png Binary files differindex 17144b673..17144b673 100644 --- a/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_holo.9.png +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_light_pressed_klp.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_ics.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_ics.9.png Binary files differnew file mode 100644 index 000000000..6d2af5942 --- /dev/null +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_ics.9.png diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_holo.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_klp.9.png Binary files differindex 0cbb2ec84..0cbb2ec84 100644 --- a/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_holo.9.png +++ b/java/res/drawable-xxhdpi/btn_keyboard_key_popup_selected_klp.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_ics.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_ics.9.png Binary files differnew file mode 100644 index 000000000..bd1ef3cd9 --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_ics.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_holo.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_klp.9.png Binary files differindex 11eee94f3..11eee94f3 100644 --- a/java/res/drawable-xxhdpi/keyboard_key_feedback_background_holo.9.png +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_ics.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_ics.9.png Binary files differnew file mode 100644 index 000000000..65af4b569 --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_ics.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_holo.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_klp.9.png Binary files differindex 2079e0462..2079e0462 100644 --- a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_holo.9.png +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_ics.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..ac6750dcb --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_ics.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_holo.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_klp.9.png Binary files differindex c4178d9a8..c4178d9a8 100644 --- a/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_holo.9.png +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_left_more_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_ics.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..cea7c05f6 --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_ics.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_holo.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_klp.9.png Binary files differindex 121411a06..121411a06 100644 --- a/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_holo.9.png +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_more_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_ics.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_ics.9.png Binary files differnew file mode 100644 index 000000000..520fa7c6b --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_ics.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_holo.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_klp.9.png Binary files differindex d3d8733fd..d3d8733fd 100644 --- a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_holo.9.png +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_ics.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_ics.9.png Binary files differnew file mode 100644 index 000000000..eee221758 --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_ics.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_holo.9.png b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_klp.9.png Binary files differindex d7ec8bcb2..d7ec8bcb2 100644 --- a/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_holo.9.png +++ b/java/res/drawable-xxhdpi/keyboard_key_feedback_right_more_background_klp.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_popup_panel_background_holo.9.png b/java/res/drawable-xxhdpi/keyboard_popup_panel_background_holo.9.png Binary files differdeleted file mode 100644 index ca576deaf..000000000 --- a/java/res/drawable-xxhdpi/keyboard_popup_panel_background_holo.9.png +++ /dev/null diff --git a/java/res/drawable-xxhdpi/keyboard_popup_panel_background_ics.9.png b/java/res/drawable-xxhdpi/keyboard_popup_panel_background_ics.9.png Binary files differnew file mode 100644 index 000000000..721c24400 --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_popup_panel_background_ics.9.png diff --git a/java/res/drawable-xxhdpi/keyboard_popup_panel_background_klp.9.png b/java/res/drawable-xxhdpi/keyboard_popup_panel_background_klp.9.png Binary files differnew file mode 100644 index 000000000..91d5d7f90 --- /dev/null +++ b/java/res/drawable-xxhdpi/keyboard_popup_panel_background_klp.9.png diff --git a/java/res/drawable/btn_keyboard_key_functional_ics.xml b/java/res/drawable/btn_keyboard_key_functional_ics.xml index 5dcde5fa9..847ca72f4 100644 --- a/java/res/drawable/btn_keyboard_key_functional_ics.xml +++ b/java/res/drawable/btn_keyboard_key_functional_ics.xml @@ -17,6 +17,6 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Functional keys. --> <item android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_dark_pressed_holo" /> + android:drawable="@drawable/btn_keyboard_key_dark_pressed_ics" /> <item android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" /> </selector> diff --git a/java/res/drawable/btn_keyboard_key_functional_klp.xml b/java/res/drawable/btn_keyboard_key_functional_klp.xml new file mode 100644 index 000000000..0e17ed234 --- /dev/null +++ b/java/res/drawable/btn_keyboard_key_functional_klp.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Functional keys. --> + <item android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_dark_pressed_klp" /> + <item android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" /> +</selector> diff --git a/java/res/drawable/btn_keyboard_key_ics.xml b/java/res/drawable/btn_keyboard_key_ics.xml index 0c86e163e..259bb9ba5 100644 --- a/java/res/drawable/btn_keyboard_key_ics.xml +++ b/java/res/drawable/btn_keyboard_key_ics.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 The Android Open Source Project +<!-- 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. @@ -17,23 +17,23 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Functional keys. --> <item android:state_single="true" android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_dark_pressed_holo" /> + android:drawable="@drawable/btn_keyboard_key_dark_pressed_ics" /> <item android:state_single="true" android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" /> <!-- Action keys. --> <item android:state_active="true" android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_dark_pressed_holo" /> + android:drawable="@drawable/btn_keyboard_key_dark_pressed_ics" /> <item android:state_active="true" - android:drawable="@drawable/btn_keyboard_key_dark_active_holo" /> + android:drawable="@drawable/btn_keyboard_key_dark_active_ics" /> <!-- Toggle keys. Use checkable/checked state. --> <item android:state_checkable="true" android:state_checked="true" android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_holo" /> + android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_ics" /> <item android:state_checkable="true" android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_dark_pressed_off_holo" /> + android:drawable="@drawable/btn_keyboard_key_dark_pressed_off_ics" /> <item android:state_checkable="true" android:state_checked="true" - android:drawable="@drawable/btn_keyboard_key_dark_normal_on_holo" /> + android:drawable="@drawable/btn_keyboard_key_dark_normal_on_ics" /> <item android:state_checkable="true" android:drawable="@drawable/btn_keyboard_key_dark_normal_off_holo" /> @@ -43,6 +43,6 @@ <!-- Normal keys. --> <item android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_light_pressed_holo" /> + android:drawable="@drawable/btn_keyboard_key_light_pressed_ics" /> <item android:drawable="@drawable/btn_keyboard_key_light_normal_holo" /> </selector> diff --git a/java/res/drawable/btn_keyboard_key_klp.xml b/java/res/drawable/btn_keyboard_key_klp.xml new file mode 100644 index 000000000..16b5fa00b --- /dev/null +++ b/java/res/drawable/btn_keyboard_key_klp.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Functional keys. --> + <item android:state_single="true" android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_dark_pressed_klp" /> + <item android:state_single="true" + android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" /> + + <!-- Action keys. --> + <item android:state_active="true" android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_dark_pressed_klp" /> + <item android:state_active="true" + android:drawable="@drawable/btn_keyboard_key_dark_active_klp" /> + + <!-- Toggle keys. Use checkable/checked state. --> + <item android:state_checkable="true" android:state_checked="true" android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_klp" /> + <item android:state_checkable="true" android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_dark_pressed_off_klp" /> + <item android:state_checkable="true" android:state_checked="true" + android:drawable="@drawable/btn_keyboard_key_dark_normal_on_klp" /> + <item android:state_checkable="true" + android:drawable="@drawable/btn_keyboard_key_dark_normal_off_holo" /> + + <!-- Empty background keys. --> + <item android:state_empty="true" + android:drawable="@drawable/transparent" /> + + <!-- Normal keys. --> + <item android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_light_pressed_klp" /> + <item android:drawable="@drawable/btn_keyboard_key_light_normal_holo" /> +</selector> diff --git a/java/res/drawable/btn_keyboard_key_popup_ics.xml b/java/res/drawable/btn_keyboard_key_popup_ics.xml index b99679ba1..31b613176 100644 --- a/java/res/drawable/btn_keyboard_key_popup_ics.xml +++ b/java/res/drawable/btn_keyboard_key_popup_ics.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 The Android Open Source Project +<!-- 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. @@ -16,6 +16,6 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_popup_selected_holo" /> + android:drawable="@drawable/btn_keyboard_key_popup_selected_ics" /> <item android:drawable="@drawable/transparent" /> </selector> diff --git a/java/res/drawable/btn_keyboard_key_popup_klp.xml b/java/res/drawable/btn_keyboard_key_popup_klp.xml new file mode 100644 index 000000000..62cbca8ae --- /dev/null +++ b/java/res/drawable/btn_keyboard_key_popup_klp.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_popup_selected_klp" /> + <item android:drawable="@drawable/transparent" /> +</selector> diff --git a/java/res/drawable/btn_suggestion_ics.xml b/java/res/drawable/btn_suggestion_ics.xml index e4257e327..8f528ee4b 100644 --- a/java/res/drawable/btn_suggestion_ics.xml +++ b/java/res/drawable/btn_suggestion_ics.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2011, The Android Open Source Project +** 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. @@ -23,5 +23,5 @@ > <item android:state_pressed="true" - android:drawable="@drawable/btn_keyboard_key_popup_selected_holo" /> + android:drawable="@drawable/btn_keyboard_key_popup_selected_ics" /> </selector> diff --git a/java/res/drawable/btn_suggestion_klp.xml b/java/res/drawable/btn_suggestion_klp.xml new file mode 100644 index 000000000..471165bdf --- /dev/null +++ b/java/res/drawable/btn_suggestion_klp.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. +*/ +--> + +<selector + xmlns:android="http://schemas.android.com/apk/res/android" +> + <item + android:state_pressed="true" + android:drawable="@drawable/btn_keyboard_key_popup_selected_klp" /> +</selector> diff --git a/java/res/drawable/keyboard_key_feedback_ics.xml b/java/res/drawable/keyboard_key_feedback_ics.xml index 3c8850e6c..b52a61fbf 100644 --- a/java/res/drawable/keyboard_key_feedback_ics.xml +++ b/java/res/drawable/keyboard_key_feedback_ics.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 The Android Open Source Project +<!-- 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. @@ -20,17 +20,17 @@ > <!-- Left edge --> <item latin:state_left_edge="true" latin:state_has_morekeys="true" - android:drawable="@drawable/keyboard_key_feedback_left_more_background_holo" /> + android:drawable="@drawable/keyboard_key_feedback_left_more_background_ics" /> <item latin:state_left_edge="true" - android:drawable="@drawable/keyboard_key_feedback_left_background_holo" /> + android:drawable="@drawable/keyboard_key_feedback_left_background_ics" /> <!-- Right edge --> <item latin:state_right_edge="true" latin:state_has_morekeys="true" - android:drawable="@drawable/keyboard_key_feedback_right_more_background_holo" /> + android:drawable="@drawable/keyboard_key_feedback_right_more_background_ics" /> <item latin:state_right_edge="true" - android:drawable="@drawable/keyboard_key_feedback_right_background_holo" /> + android:drawable="@drawable/keyboard_key_feedback_right_background_ics" /> <item latin:state_has_morekeys="true" - android:drawable="@drawable/keyboard_key_feedback_more_background_holo" /> - <item android:drawable="@drawable/keyboard_key_feedback_background_holo" /> + android:drawable="@drawable/keyboard_key_feedback_more_background_ics" /> + <item android:drawable="@drawable/keyboard_key_feedback_background_ics" /> </selector> diff --git a/java/res/drawable/keyboard_key_feedback_klp.xml b/java/res/drawable/keyboard_key_feedback_klp.xml new file mode 100644 index 000000000..a38655641 --- /dev/null +++ b/java/res/drawable/keyboard_key_feedback_klp.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- Left edge --> + <item latin:state_left_edge="true" latin:state_has_morekeys="true" + android:drawable="@drawable/keyboard_key_feedback_left_more_background_klp" /> + <item latin:state_left_edge="true" + android:drawable="@drawable/keyboard_key_feedback_left_background_klp" /> + + <!-- Right edge --> + <item latin:state_right_edge="true" latin:state_has_morekeys="true" + android:drawable="@drawable/keyboard_key_feedback_right_more_background_klp" /> + <item latin:state_right_edge="true" + android:drawable="@drawable/keyboard_key_feedback_right_background_klp" /> + + <item latin:state_has_morekeys="true" + android:drawable="@drawable/keyboard_key_feedback_more_background_klp" /> + <item android:drawable="@drawable/keyboard_key_feedback_background_klp" /> +</selector> diff --git a/java/res/layout/emoji_keyboard_page.xml b/java/res/layout/emoji_keyboard_page.xml index e0b752b32..9afad366a 100644 --- a/java/res/layout/emoji_keyboard_page.xml +++ b/java/res/layout/emoji_keyboard_page.xml @@ -18,16 +18,9 @@ */ --> -<com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier +<com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/emoji_keyboard_scroller" - android:clipToPadding="false" - android:layout_width="match_parent" - android:layout_height="match_parent" -> - <com.android.inputmethod.keyboard.internal.ScrollKeyboardView - android:id="@+id/emoji_keyboard_page" - android:layoutDirection="ltr" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> -</com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier> + android:id="@+id/emoji_keyboard_page" + android:layoutDirection="ltr" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> diff --git a/java/res/layout/key_preview_ics.xml b/java/res/layout/key_preview_ics.xml index 222e8846c..33b6947ef 100644 --- a/java/res/layout/key_preview_ics.xml +++ b/java/res/layout/key_preview_ics.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2012, The Android Open Source Project +** 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. diff --git a/java/res/layout/key_preview_klp.xml b/java/res/layout/key_preview_klp.xml new file mode 100644 index 000000000..160aeb9a9 --- /dev/null +++ b/java/res/layout/key_preview_klp.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. +*/ +--> + +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/keyboard_key_feedback_klp" + android:minWidth="32dp" + android:gravity="center" +/> diff --git a/java/res/raw/setup_welcome_image.png b/java/res/raw/setup_welcome_image.png Binary files differindex 2445915b8..98e731331 100644 --- a/java/res/raw/setup_welcome_image.png +++ b/java/res/raw/setup_welcome_image.png diff --git a/java/res/raw/setup_welcome_video.mp4 b/java/res/raw/setup_welcome_video.mp4 Binary files differindex 820852531..224bf250c 100644 --- a/java/res/raw/setup_welcome_video.mp4 +++ b/java/res/raw/setup_welcome_video.mp4 diff --git a/java/res/values-af/strings-action-keys.xml b/java/res/values-af/strings-action-keys.xml new file mode 100644 index 000000000..615dc1205 --- /dev/null +++ b/java/res/values-af/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Gaan"</string> + <string name="label_next_key" msgid="362972844525672568">"Volgende"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Vorige"</string> + <string name="label_done_key" msgid="2441578748772529288">"Klaar"</string> + <string name="label_send_key" msgid="2815056534433717444">"Stuur"</string> + <string name="label_pause_key" msgid="181098308428035340">"Laat wag"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Wag"</string> +</resources> diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml index a3c95b290..a4ae86b41 100644 --- a/java/res/values-af/strings.xml +++ b/java/res/values-af/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dinamiese sweefvoorskou"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Sien die voorgestelde woord tydens gebare"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Gestoor"</string> - <string name="label_go_key" msgid="1635148082137219148">"Gaan"</string> - <string name="label_next_key" msgid="362972844525672568">"Volgende"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Vorige"</string> - <string name="label_done_key" msgid="2441578748772529288">"Klaar"</string> - <string name="label_send_key" msgid="2815056534433717444">"Stuur"</string> - <string name="label_pause_key" msgid="181098308428035340">"Laat wag"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Wag"</string> <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-action-keys.xml b/java/res/values-am/strings-action-keys.xml new file mode 100644 index 000000000..45196a4b4 --- /dev/null +++ b/java/res/values-am/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml index 89e37b274..a29e22987 100644 --- a/java/res/values-am/strings.xml +++ b/java/res/values-am/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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 +154,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-action-keys.xml b/java/res/values-ar/strings-action-keys.xml new file mode 100644 index 000000000..99e8f6a73 --- /dev/null +++ b/java/res/values-ar/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-ar/strings-appname.xml b/java/res/values-ar/strings-appname.xml index d5176d022..35387cb86 100644 --- a/java/res/values-ar/strings-appname.xml +++ b/java/res/values-ar/strings-appname.xml @@ -20,8 +20,8 @@ <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> + <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-ar/strings.xml b/java/res/values-ar/strings.xml index 9c3ff51c8..71f92fb5d 100644 --- a/java/res/values-ar/strings.xml +++ b/java/res/values-ar/strings.xml @@ -38,7 +38,7 @@ <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 أو Symbol"</string> + <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"عرض تلميح مرئي أثناء التمرير من مفتاح Shift أو Symbol"</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> @@ -74,24 +74,15 @@ <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_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_description_unknown" msgid="3197434010402179157">"رمز المفتاح %d"</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">"العالي"</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_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> @@ -107,9 +98,9 @@ <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_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> @@ -124,7 +115,7 @@ <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="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> @@ -149,12 +140,12 @@ <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_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> @@ -219,9 +210,9 @@ <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/> نوصي <b>بتنزيل</b> قاموس <xliff:g id="LANGUAGE">%1$s</xliff:g> لتحسين تجربة الكتابة.<br/> <br/> قد يستغرق التنزيل دقيقة أو دقيقتين أكثر من المدة التي يستغرقها التنزيل عبر شبكة الجيل الثالث. قد تنطبق الرسوم إذا لم تكن مشتركًا في <b>خطة البيانات غير المحدودة</b>.<br/> إذا لم تكن متأكدًا من خطة البيانات المتوفرة لديك، فنحن نوصي بالبحث عن اتصال Wi-Fi لبدء عملية التنزيل تلقائيًا.<br/> <br/> نصيحة: يمكنك تنزيل القواميس وإزالتها عن طريق الانتقال إلى <b>اللغة والإدخال</b> في قائمة <b>إعدادات</b> في جهازك الجوَّال."</string> + <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"اللغة المحددة على جهازك الجوال تشتمل على قاموس متوفر.<br/> نوصي <b>بتنزيل</b> قاموس <xliff:g id="LANGUAGE">%1$s</xliff:g> لتحسين تجربة الكتابة.<br/> <br/> قد يستغرق التنزيل دقيقة أو دقيقتين أكثر من المدة التي يستغرقها التنزيل عبر شبكة الجيل الثالث. قد تنطبق الرسوم إذا لم تكن مشتركًا في <b>خطة البيانات غير المحدودة</b>.<br/> إذا لم تكن متأكدًا من خطة البيانات المتوفرة لديك، فنحن نوصي بالبحث عن اتصال Wi-Fi لبدء عملية التنزيل تلقائيًا.<br/> <br/> نصيحة: يمكنك تنزيل القواميس وإزالتها عن طريق الانتقال إلى <b>اللغة والإدخال</b> في قائمة <b>إعدادات</b> في جهازك الجوَّال."</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="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> diff --git a/java/res/values-be/strings-action-keys.xml b/java/res/values-be/strings-action-keys.xml new file mode 100644 index 000000000..91416c8b7 --- /dev/null +++ b/java/res/values-be/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml index 9e591dea9..02972f07e 100644 --- a/java/res/values-be/strings.xml +++ b/java/res/values-be/strings.xml @@ -77,19 +77,12 @@ <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">"Каб праслухаць парол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-action-keys.xml b/java/res/values-bg/strings-action-keys.xml new file mode 100644 index 000000000..609bf415b --- /dev/null +++ b/java/res/values-bg/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml index c21b53490..69dec9661 100644 --- a/java/res/values-bg/strings.xml +++ b/java/res/values-bg/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-ca/strings-action-keys.xml new file mode 100644 index 000000000..0c0c84efd --- /dev/null +++ b/java/res/values-ca/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Vés"</string> + <string name="label_next_key" msgid="362972844525672568">"Següent"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> + <string name="label_done_key" msgid="2441578748772529288">"Fet"</string> + <string name="label_send_key" msgid="2815056534433717444">"Envia"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Espera"</string> +</resources> diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml index d791452d4..95021211d 100644 --- a/java/res/values-ca/strings.xml +++ b/java/res/values-ca/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Visualitz. prèvia dinàmica flotant"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Consulta la paraula suggerida mentre fas el gest"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: desada"</string> - <string name="label_go_key" msgid="1635148082137219148">"Vés"</string> - <string name="label_next_key" msgid="362972844525672568">"Següent"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> - <string name="label_done_key" msgid="2441578748772529288">"Fet"</string> - <string name="label_send_key" msgid="2815056534433717444">"Envia"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Espera"</string> <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-action-keys.xml b/java/res/values-cs/strings-action-keys.xml new file mode 100644 index 000000000..700fc78f2 --- /dev/null +++ b/java/res/values-cs/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Přejít"</string> + <string name="label_next_key" msgid="362972844525672568">"Další"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Před."</string> + <string name="label_done_key" msgid="2441578748772529288">"Hotovo"</string> + <string name="label_send_key" msgid="2815056534433717444">"Odeslat"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pauza"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Čekat"</string> +</resources> diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml index 2cd159d0f..0f38f45ca 100644 --- a/java/res/values-cs/strings.xml +++ b/java/res/values-cs/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamický plovoucí náhled"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Zobrazení navrhovaného slova při psaní gesty"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Uloženo"</string> - <string name="label_go_key" msgid="1635148082137219148">"Přejít"</string> - <string name="label_next_key" msgid="362972844525672568">"Další"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Před."</string> - <string name="label_done_key" msgid="2441578748772529288">"Hotovo"</string> - <string name="label_send_key" msgid="2815056534433717444">"Odeslat"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pauza"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Čekat"</string> <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-action-keys.xml b/java/res/values-da/strings-action-keys.xml new file mode 100644 index 000000000..332f2830d --- /dev/null +++ b/java/res/values-da/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Gå"</string> + <string name="label_next_key" msgid="362972844525672568">"Næste"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Forr."</string> + <string name="label_done_key" msgid="2441578748772529288">"Udfør"</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">"Vent"</string> +</resources> diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index 6c9d9d786..839d7cd9e 100644 --- a/java/res/values-da/strings.xml +++ b/java/res/values-da/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamisk flydende eks.visning"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Se det foreslåede ord, mens berøringer udføres"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Gemt"</string> - <string name="label_go_key" msgid="1635148082137219148">"Gå"</string> - <string name="label_next_key" msgid="362972844525672568">"Næste"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Forr."</string> - <string name="label_done_key" msgid="2441578748772529288">"Udfør"</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">"Vent"</string> <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 +185,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-action-keys.xml b/java/res/values-de/strings-action-keys.xml new file mode 100644 index 000000000..5ec047546 --- /dev/null +++ b/java/res/values-de/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Los"</string> + <string name="label_next_key" msgid="362972844525672568">"Weiter"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Zurück"</string> + <string name="label_done_key" msgid="2441578748772529288">"Fertig"</string> + <string name="label_send_key" msgid="2815056534433717444">"Senden"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pause"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Warten"</string> +</resources> diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml index 1a4e38542..5e35b9ff9 100644 --- a/java/res/values-de/strings.xml +++ b/java/res/values-de/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dyn. unverankerter Vorschlag"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Vorgeschlagenes Wort bei Bewegung anzeigen"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: gespeichert"</string> - <string name="label_go_key" msgid="1635148082137219148">"Los"</string> - <string name="label_next_key" msgid="362972844525672568">"Weiter"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Zurück"</string> - <string name="label_done_key" msgid="2441578748772529288">"Fertig"</string> - <string name="label_send_key" msgid="2815056534433717444">"Senden"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pause"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Warten"</string> <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-action-keys.xml b/java/res/values-el/strings-action-keys.xml new file mode 100644 index 000000000..b890c4b1d --- /dev/null +++ b/java/res/values-el/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml index c2ee2d39b..a719077c0 100644 --- a/java/res/values-el/strings.xml +++ b/java/res/values-el/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-en-rGB/strings-action-keys.xml new file mode 100644 index 000000000..062907c76 --- /dev/null +++ b/java/res/values-en-rGB/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml index 0586bcca4..9e860ecfa 100644 --- a/java/res/values-en-rGB/strings.xml +++ b/java/res/values-en-rGB/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-en-rIN/strings-action-keys.xml new file mode 100644 index 000000000..062907c76 --- /dev/null +++ b/java/res/values-en-rIN/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> 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..9e860ecfa --- /dev/null +++ b/java/res/values-en-rIN/strings.xml @@ -0,0 +1,239 @@ +<?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="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 & 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 & 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.<br/> We recommend <b>downloading</b> the <xliff:g id="LANGUAGE">%1$s</xliff:g> dictionary to improve your typing experience.<br/> <br/> The download could take a minute or two over 3G. Charges may apply if you don\'t have an <b>unlimited data plan</b>.<br/> If you are not sure which data plan you have, we recommend finding a Wi-Fi connection to start the download automatically.<br/> <br/> Tip: You can download and remove dictionaries by going to <b>Language & input</b> in the <b>Settings</b> 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-action-keys.xml b/java/res/values-es-rUS/strings-action-keys.xml new file mode 100644 index 000000000..b3ad7094b --- /dev/null +++ b/java/res/values-es-rUS/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> + <string name="label_next_key" msgid="362972844525672568">"Siguiente"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> + <string name="label_done_key" msgid="2441578748772529288">"Listo"</string> + <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Espera"</string> +</resources> diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml index 42c3932f6..1ac080e9c 100644 --- a/java/res/values-es-rUS/strings.xml +++ b/java/res/values-es-rUS/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Vista previa dinámica flotante"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Mira la palabra sugerida mientras haces gestos"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string> - <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> - <string name="label_next_key" msgid="362972844525672568">"Siguiente"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> - <string name="label_done_key" msgid="2441578748772529288">"Listo"</string> - <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Espera"</string> <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-action-keys.xml b/java/res/values-es/strings-action-keys.xml new file mode 100644 index 000000000..7c0035074 --- /dev/null +++ b/java/res/values-es/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> + <string name="label_next_key" msgid="362972844525672568">"Sig."</string> + <string name="label_previous_key" msgid="1211868118071386787">"Anterior"</string> + <string name="label_done_key" msgid="2441578748772529288">"Ok"</string> + <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Espera"</string> +</resources> diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml index 4d72799f4..d9477da93 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> @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Vista previa dinámica flotante"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Ver palabra sugerida al hacer gestos"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string> - <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> - <string name="label_next_key" msgid="362972844525672568">"Sig."</string> - <string name="label_previous_key" msgid="1211868118071386787">"Anterior"</string> - <string name="label_done_key" msgid="2441578748772529288">"Ok"</string> - <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Espera"</string> <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 +119,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-action-keys.xml b/java/res/values-et-rEE/strings-action-keys.xml new file mode 100644 index 000000000..07bdb8491 --- /dev/null +++ b/java/res/values-et-rEE/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Mine"</string> + <string name="label_next_key" msgid="362972844525672568">"Edasi"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Eelm."</string> + <string name="label_done_key" msgid="2441578748772529288">"Valmis"</string> + <string name="label_send_key" msgid="2815056534433717444">"Saada"</string> + <string name="label_pause_key" msgid="181098308428035340">"Peata"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Oota"</string> +</resources> diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml index 5706fa105..dc46e8cb2 100644 --- a/java/res/values-et-rEE/strings.xml +++ b/java/res/values-et-rEE/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dünaamiline ujuv eelvaade"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Soovitatud sõna vaatamine joonistusega sisestamise ajal"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : salvestatud"</string> - <string name="label_go_key" msgid="1635148082137219148">"Mine"</string> - <string name="label_next_key" msgid="362972844525672568">"Edasi"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Eelm."</string> - <string name="label_done_key" msgid="2441578748772529288">"Valmis"</string> - <string name="label_send_key" msgid="2815056534433717444">"Saada"</string> - <string name="label_pause_key" msgid="181098308428035340">"Peata"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Oota"</string> <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-action-keys.xml b/java/res/values-fa/strings-action-keys.xml new file mode 100644 index 000000000..a3262ed73 --- /dev/null +++ b/java/res/values-fa/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-fa/strings-appname.xml b/java/res/values-fa/strings-appname.xml index 38234c241..f6c9f545e 100644 --- a/java/res/values-fa/strings-appname.xml +++ b/java/res/values-fa/strings-appname.xml @@ -20,8 +20,8 @@ <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> + <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-fa/strings.xml b/java/res/values-fa/strings.xml index c03e440e4..cfd33c259 100644 --- a/java/res/values-fa/strings.xml +++ b/java/res/values-fa/strings.xml @@ -38,7 +38,7 @@ <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="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> @@ -74,28 +74,19 @@ <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.format failed for translation --> <!-- 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 /> <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_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> @@ -111,9 +102,9 @@ <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_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> @@ -153,12 +144,12 @@ <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_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> @@ -223,9 +214,9 @@ <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/> توصیه میکنیم فرهنگ لغت <xliff:g id="LANGUAGE">%1$s</xliff:g> را <b>دانلود کنید</b> تا بهتر تایپ کنید.<br/> <br/> دانلود از طریق 3G ممکن است چند لحظه طول بکشد. اگر <b>طرح داده نامحدود</b> نداشته باشید ممکن است برایتان هزینه داشته باشد.<br/> اگر مطمئن نیستید طرح داده شما چیست٬ توصیه میکنیم یک اتصال Wi-Fi پیدا کنید تا دانلود بطور خودکار شروع شود.<br/> <br/> نکته: میتوانید فرهنگ لغت را با رفتن به منوی <b>زبان و ورودی</b> در <b>تنظیمات</b> در دستگاه همراه خود دانلود و حذف کنید."</string> + <string name="should_download_over_metered_prompt" msgid="2878629598667658845">"برای زبان انتخاب شده در دستگاه همراه شما فرهنگ لغتی موجود است.<br/> توصیه میکنیم فرهنگ لغت <xliff:g id="LANGUAGE">%1$s</xliff:g> را <b>دانلود کنید</b> تا بهتر تایپ کنید.<br/> <br/> دانلود از طریق 3G ممکن است چند لحظه طول بکشد. اگر <b>طرح داده نامحدود</b> نداشته باشید ممکن است برایتان هزینه داشته باشد.<br/> اگر مطمئن نیستید طرح داده شما چیست٬ توصیه میکنیم یک اتصال Wi-Fi پیدا کنید تا دانلود بطور خودکار شروع شود.<br/> <br/> نکته: میتوانید فرهنگ لغت را با رفتن به منوی <b>زبان و ورودی</b> در <b>تنظیمات</b> در دستگاه همراه خود دانلود و حذف کنید."</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="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> diff --git a/java/res/values-fi/strings-action-keys.xml b/java/res/values-fi/strings-action-keys.xml new file mode 100644 index 000000000..dfe1d8e73 --- /dev/null +++ b/java/res/values-fi/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Mene"</string> + <string name="label_next_key" msgid="362972844525672568">"Seur."</string> + <string name="label_previous_key" msgid="1211868118071386787">"Edel."</string> + <string name="label_done_key" msgid="2441578748772529288">"Valmis"</string> + <string name="label_send_key" msgid="2815056534433717444">"Läh."</string> + <string name="label_pause_key" msgid="181098308428035340">"Tauko"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Odota"</string> +</resources> diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml index 744e60420..cc2dcd6cf 100644 --- a/java/res/values-fi/strings.xml +++ b/java/res/values-fi/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynaaminen kelluva esikatselu"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Näytä ehdotettu sana piirron aikana"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: tallennettu"</string> - <string name="label_go_key" msgid="1635148082137219148">"Mene"</string> - <string name="label_next_key" msgid="362972844525672568">"Seur."</string> - <string name="label_previous_key" msgid="1211868118071386787">"Edel."</string> - <string name="label_done_key" msgid="2441578748772529288">"Valmis"</string> - <string name="label_send_key" msgid="2815056534433717444">"Läh."</string> - <string name="label_pause_key" msgid="181098308428035340">"Tauko"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Odota"</string> <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-action-keys.xml b/java/res/values-fr-rCA/strings-action-keys.xml new file mode 100644 index 000000000..774e502da --- /dev/null +++ b/java/res/values-fr-rCA/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> 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..61df43282 100644 --- a/java/res/values-fr-rCA/strings.xml +++ b/java/res/values-fr-rCA/strings.xml @@ -1,19 +1,239 @@ <?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="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.<br/> Nous vous invitons à <b>télécharger</b> le dictionnaire <xliff:g id="LANGUAGE">%1$s</xliff:g> pour faciliter votre saisie.<br/> <br/> 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 <b>forfait Internet illimité</b>.<br/> 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.<br/> <br/> Astuce : Vous pouvez télécharger et supprimer des dictionnaires dans la section <b>Langue et saisie</b> du menu <b>Paramètres</b> 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-action-keys.xml b/java/res/values-fr/strings-action-keys.xml new file mode 100644 index 000000000..a22b78816 --- /dev/null +++ b/java/res/values-fr/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"OK"</string> + <string name="label_next_key" msgid="362972844525672568">"Suiv."</string> + <string name="label_previous_key" msgid="1211868118071386787">"Préc."</string> + <string name="label_done_key" msgid="2441578748772529288">"OK"</string> + <string name="label_send_key" msgid="2815056534433717444">"Envoi"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pause"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Délai"</string> +</resources> diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml index 5fedd4ebd..c0840b221 100644 --- a/java/res/values-fr/strings.xml +++ b/java/res/values-fr/strings.xml @@ -74,20 +74,11 @@ <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">"OK"</string> - <string name="label_next_key" msgid="362972844525672568">"Suiv."</string> - <string name="label_previous_key" msgid="1211868118071386787">"Préc."</string> - <string name="label_done_key" msgid="2441578748772529288">"OK"</string> - <string name="label_send_key" msgid="2815056534433717444">"Envoi"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pause"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Délai"</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> - <!-- 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-action-keys.xml b/java/res/values-hi/strings-action-keys.xml new file mode 100644 index 000000000..456aece7c --- /dev/null +++ b/java/res/values-hi/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml index 3b3228a9f..08d7315a5 100644 --- a/java/res/values-hi/strings.xml +++ b/java/res/values-hi/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-hr/strings-action-keys.xml new file mode 100644 index 000000000..c475c799f --- /dev/null +++ b/java/res/values-hr/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Idi"</string> + <string name="label_next_key" msgid="362972844525672568">"Dalje"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Pret."</string> + <string name="label_done_key" msgid="2441578748772529288">"Gotovo"</string> + <string name="label_send_key" msgid="2815056534433717444">"Pošalji"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pauza"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Pričekaj"</string> +</resources> diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml index caef9541d..e5f4731ba 100644 --- a/java/res/values-hr/strings.xml +++ b/java/res/values-hr/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dinamički plutajući pregled"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Vidi predloženu riječ tijekom pokreta"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Spremljeno"</string> - <string name="label_go_key" msgid="1635148082137219148">"Idi"</string> - <string name="label_next_key" msgid="362972844525672568">"Dalje"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Pret."</string> - <string name="label_done_key" msgid="2441578748772529288">"Gotovo"</string> - <string name="label_send_key" msgid="2815056534433717444">"Pošalji"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pauza"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Pričekaj"</string> <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-action-keys.xml b/java/res/values-hu/strings-action-keys.xml new file mode 100644 index 000000000..eb72ac8d0 --- /dev/null +++ b/java/res/values-hu/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Ugrás"</string> + <string name="label_next_key" msgid="362972844525672568">"Tovább"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Előző"</string> + <string name="label_done_key" msgid="2441578748772529288">"Kész"</string> + <string name="label_send_key" msgid="2815056534433717444">"Küldés"</string> + <string name="label_pause_key" msgid="181098308428035340">"Szün."</string> + <string name="label_wait_key" msgid="6402152600878093134">"Vár"</string> +</resources> diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml index 3b0ee4798..bcd229675 100644 --- a/java/res/values-hu/strings.xml +++ b/java/res/values-hu/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dinamikus lebegő előnézet"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"A javasolt szó megtekintése kézmozdulat közben"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : mentve"</string> - <string name="label_go_key" msgid="1635148082137219148">"Ugrás"</string> - <string name="label_next_key" msgid="362972844525672568">"Tovább"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Előző"</string> - <string name="label_done_key" msgid="2441578748772529288">"Kész"</string> - <string name="label_send_key" msgid="2815056534433717444">"Küldés"</string> - <string name="label_pause_key" msgid="181098308428035340">"Szün."</string> - <string name="label_wait_key" msgid="6402152600878093134">"Vár"</string> <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-action-keys.xml b/java/res/values-hy-rAM/strings-action-keys.xml new file mode 100644 index 000000000..f9400559f --- /dev/null +++ b/java/res/values-hy-rAM/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> 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..76b0a08b9 --- /dev/null +++ b/java/res/values-hy-rAM/strings.xml @@ -0,0 +1,239 @@ +<?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="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>»-ը ձեր Լեզվի & մուտքագրման կարգավորումներում: Դա կլիազորի նրան գործարկվել ձեր սարքում:"</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">"Ձեր բջջային սարքում ընտրված լեզվով առկա է բառարան:<br/> Խորհուրդ ենք տալիս <b>ներբեռնել</b> <xliff:g id="LANGUAGE">%1$s</xliff:g> բառարանը ձեր մուտքագրման հմտությունների բարելավման համար:<br/> <br/> Ներբեռնումը կարող է խլել մեկ կամ երկու րոպե 3G-ի դեպքում: Հնարավոր է գանձում կատարվի, եթե դուք չունեք <b>տվյալների անսահմանափակ փաթեթ</b>.<br/> Եթե դուք վստահ չեք, թե տվյալների որ փաթեթն ունեք, խորհուրդ ենք տալիս գտնել Wi-Fi կապ՝ ներբեռնումն ավտոմատ սկսելու համար:<br/> <br/> Հուշում. դուք կարող եք ներբեռնել և հեռացնել բառարաններ՝ գնալով ձեր բջջային սարքի <b>Կարգավորումներ ցանկի Լեզու & մուտքագրման</b> բաժինը:"</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-action-keys.xml b/java/res/values-in/strings-action-keys.xml new file mode 100644 index 000000000..85f7e7809 --- /dev/null +++ b/java/res/values-in/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Buka"</string> + <string name="label_next_key" msgid="362972844525672568">"Berikutnya"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Sblm"</string> + <string name="label_done_key" msgid="2441578748772529288">"Selesai"</string> + <string name="label_send_key" msgid="2815056534433717444">"Kirimkan"</string> + <string name="label_pause_key" msgid="181098308428035340">"Jeda"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Tunggu"</string> +</resources> diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml index bfbd2a700..99aa8640a 100644 --- a/java/res/values-in/strings.xml +++ b/java/res/values-in/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Pratinjau mengambang dinamis"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Lihat kata yang disarankan saat melakukan isyarat"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Telah disimpan"</string> - <string name="label_go_key" msgid="1635148082137219148">"Buka"</string> - <string name="label_next_key" msgid="362972844525672568">"Berikutnya"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Sblm"</string> - <string name="label_done_key" msgid="2441578748772529288">"Selesai"</string> - <string name="label_send_key" msgid="2815056534433717444">"Kirimkan"</string> - <string name="label_pause_key" msgid="181098308428035340">"Jeda"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Tunggu"</string> <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-is/strings-action-keys.xml b/java/res/values-is/strings-action-keys.xml new file mode 100644 index 000000000..49c6199c5 --- /dev/null +++ b/java/res/values-is/strings-action-keys.xml @@ -0,0 +1,31 @@ +<?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:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Áfram"</string> + <string name="label_next_key" msgid="362972844525672568">"Næsta"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Fyrra"</string> + <string name="label_done_key" msgid="2441578748772529288">"Lokið"</string> + <string name="label_send_key" msgid="2815056534433717444">"Senda"</string> + <!-- no translation found for label_pause_key (181098308428035340) --> + <skip /> + <!-- no translation found for label_wait_key (6402152600878093134) --> + <skip /> +</resources> diff --git a/java/res/values-is/strings.xml b/java/res/values-is/strings.xml new file mode 100644 index 000000000..6f685d395 --- /dev/null +++ b/java/res/values-is/strings.xml @@ -0,0 +1,455 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- no translation found for english_ime_input_options (3909945612939668554) --> + <skip /> + <!-- no translation found for english_ime_research_log (8492602295696577851) --> + <skip /> + <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) --> + <skip /> + <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) --> + <skip /> + <!-- no translation found for vibrate_on_keypress (5258079494276955460) --> + <skip /> + <!-- no translation found for sound_on_keypress (6093592297198243644) --> + <skip /> + <!-- no translation found for popup_on_keypress (123894815723512944) --> + <skip /> + <!-- no translation found for general_category (1859088467017573195) --> + <skip /> + <!-- no translation found for correction_category (2236750915056607613) --> + <skip /> + <!-- no translation found for gesture_typing_category (497263612130532630) --> + <skip /> + <!-- no translation found for misc_category (6894192814868233453) --> + <skip /> + <!-- no translation found for advanced_settings (362895144495591463) --> + <skip /> + <!-- no translation found for advanced_settings_summary (4487980456152830271) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for show_language_switch_key (5915478828318774384) --> + <skip /> + <!-- no translation found for show_language_switch_key_summary (7343403647474265713) --> + <skip /> + <!-- no translation found for sliding_key_input_preview (6604262359510068370) --> + <skip /> + <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) --> + <skip /> + <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) --> + <skip /> + <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) --> + <skip /> + <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) --> + <skip /> + <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) --> + <skip /> + <!-- no translation found for settings_system_default (6268225104743331821) --> + <skip /> + <!-- no translation found for use_contacts_dict (4435317977804180815) --> + <skip /> + <!-- no translation found for use_contacts_dict_summary (6599983334507879959) --> + <skip /> + <!-- no translation found for use_double_space_period (8781529969425082860) --> + <skip /> + <!-- no translation found for use_double_space_period_summary (6532892187247952799) --> + <skip /> + <!-- no translation found for auto_cap (1719746674854628252) --> + <skip /> + <!-- no translation found for auto_cap_summary (7934452761022946874) --> + <skip /> + <!-- no translation found for edit_personal_dictionary (3996910038952940420) --> + <skip /> + <!-- no translation found for configure_dictionaries_title (4238652338556902049) --> + <skip /> + <!-- no translation found for main_dictionary (4798763781818361168) --> + <skip /> + <!-- no translation found for prefs_show_suggestions (8026799663445531637) --> + <skip /> + <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) --> + <skip /> + <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) --> + <skip /> + <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) --> + <skip /> + <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) --> + <skip /> + <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) --> + <skip /> + <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) --> + <skip /> + <!-- no translation found for auto_correction (7630720885194996950) --> + <skip /> + <!-- no translation found for auto_correction_summary (5625751551134658006) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) --> + <skip /> + <!-- no translation found for bigram_prediction (1084449187723948550) --> + <skip /> + <!-- no translation found for bigram_prediction_summary (3896362682751109677) --> + <skip /> + <!-- no translation found for gesture_input (826951152254563827) --> + <skip /> + <!-- no translation found for gesture_input_summary (9180350639305731231) --> + <skip /> + <!-- no translation found for gesture_preview_trail (3802333369335722221) --> + <skip /> + <!-- no translation found for gesture_floating_preview_text (4443240334739381053) --> + <skip /> + <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) --> + <skip /> + <!-- no translation found for added_word (8993883354622484372) --> + <skip /> + <!-- no translation found for spoken_use_headphones (896961781287283493) --> + <skip /> + <!-- no translation found for spoken_current_text_is (2485723011272583845) --> + <skip /> + <!-- no translation found for spoken_no_text_entered (7479685225597344496) --> + <skip /> + <!-- no translation found for spoken_auto_correct (8005997889020109763) --> + <skip /> + <!-- no translation found for spoken_auto_correct_obscured (6276420476908833791) --> + <skip /> + <!-- no translation found for spoken_description_unknown (3197434010402179157) --> + <skip /> + <!-- no translation found for spoken_description_shift (244197883292549308) --> + <skip /> + <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) --> + <skip /> + <!-- no translation found for spoken_description_caps_lock (3276478269526304432) --> + <skip /> + <!-- no translation found for spoken_description_delete (8740376944276199801) --> + <skip /> + <!-- no translation found for spoken_description_to_symbol (5486340107500448969) --> + <skip /> + <!-- no translation found for spoken_description_to_alpha (23129338819771807) --> + <skip /> + <!-- no translation found for spoken_description_to_numeric (591752092685161732) --> + <skip /> + <!-- no translation found for spoken_description_settings (4627462689603838099) --> + <skip /> + <!-- no translation found for spoken_description_tab (2667716002663482248) --> + <skip /> + <!-- no translation found for spoken_description_space (2582521050049860859) --> + <skip /> + <!-- no translation found for spoken_description_mic (615536748882611950) --> + <skip /> + <!-- no translation found for spoken_description_smiley (2256309826200113918) --> + <skip /> + <!-- no translation found for spoken_description_return (8178083177238315647) --> + <skip /> + <!-- no translation found for spoken_description_search (1247236163755920808) --> + <skip /> + <!-- no translation found for spoken_description_dot (40711082435231673) --> + <skip /> + <!-- no translation found for spoken_description_language_switch (5507091328222331316) --> + <skip /> + <!-- no translation found for spoken_description_action_next (8636078276664150324) --> + <skip /> + <!-- no translation found for spoken_description_action_previous (800872415009336208) --> + <skip /> + <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) --> + <skip /> + <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) --> + <skip /> + <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) --> + <skip /> + <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) --> + <skip /> + <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) --> + <skip /> + <!-- no translation found for spoken_description_mode_phone (6520207943132026264) --> + <skip /> + <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) --> + <skip /> + <!-- no translation found for announce_keyboard_hidden (8718927835531429807) --> + <skip /> + <!-- no translation found for announce_keyboard_mode (4729081055438508321) --> + <skip /> + <!-- no translation found for keyboard_mode_date (3137520166817128102) --> + <skip /> + <!-- no translation found for keyboard_mode_date_time (339593358488851072) --> + <skip /> + <!-- no translation found for keyboard_mode_email (6216248078128294262) --> + <skip /> + <!-- no translation found for keyboard_mode_im (1137405089766557048) --> + <skip /> + <!-- no translation found for keyboard_mode_number (7991623440699957069) --> + <skip /> + <!-- no translation found for keyboard_mode_phone (6851627527401433229) --> + <skip /> + <!-- no translation found for keyboard_mode_text (6479436687899701619) --> + <skip /> + <!-- no translation found for keyboard_mode_time (4381856885582143277) --> + <skip /> + <!-- no translation found for keyboard_mode_url (1519819835514911218) --> + <skip /> + <!-- no translation found for voice_input (3583258583521397548) --> + <skip /> + <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> + <skip /> + <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) --> + <skip /> + <!-- no translation found for voice_input_modes_off (3745699748218082014) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_off (63875609591897607) --> + <skip /> + <!-- no translation found for configure_input_method (373356270290742459) --> + <skip /> + <!-- no translation found for language_selection_title (1651299598555326750) --> + <skip /> + <!-- no translation found for send_feedback (1780431884109392046) --> + <skip /> + <!-- no translation found for select_language (3693815588777926848) --> + <skip /> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> + <!-- no translation found for has_dictionary (6071847973466625007) --> + <skip /> + <!-- no translation found for prefs_enable_log (6620424505072963557) --> + <skip /> + <!-- no translation found for prefs_description_log (7525225584555429211) --> + <skip /> + <!-- no translation found for keyboard_layout (8451164783510487501) --> + <skip /> + <!-- no translation found for subtype_en_GB (88170601942311355) --> + <skip /> + <!-- no translation found for subtype_en_US (6160452336634534239) --> + <skip /> + <!-- no translation found for subtype_es_US (5583145191430180200) --> + <skip /> + <!-- no translation found for subtype_with_layout_en_GB (2179097748724725906) --> + <skip /> + <!-- no translation found for subtype_with_layout_en_US (1362581347576714579) --> + <skip /> + <!-- no translation found for subtype_with_layout_es_US (6261791057007890189) --> + <skip /> + <!-- no translation found for subtype_nepali_traditional (9032247506728040447) --> + <skip /> + <!-- no translation found for subtype_no_language (7137390094240139495) --> + <skip /> + <!-- no translation found for subtype_no_language_qwerty (244337630616742604) --> + <skip /> + <!-- no translation found for subtype_no_language_qwertz (443066912507547976) --> + <skip /> + <!-- no translation found for subtype_no_language_azerty (8144348527575640087) --> + <skip /> + <!-- no translation found for subtype_no_language_dvorak (1564494667584718094) --> + <skip /> + <!-- no translation found for subtype_no_language_colemak (5837418400010302623) --> + <skip /> + <!-- no translation found for subtype_no_language_pcqwerty (5354918232046200018) --> + <skip /> + <!-- no translation found for subtype_emoji (7483586578074549196) --> + <skip /> + <!-- no translation found for custom_input_styles_title (8429952441821251512) --> + <skip /> + <!-- no translation found for add_style (6163126614514489951) --> + <skip /> + <!-- no translation found for add (8299699805688017798) --> + <skip /> + <!-- no translation found for remove (4486081658752944606) --> + <skip /> + <!-- no translation found for save (7646738597196767214) --> + <skip /> + <!-- no translation found for subtype_locale (8576443440738143764) --> + <skip /> + <!-- no translation found for keyboard_layout_set (4309233698194565609) --> + <skip /> + <!-- no translation found for custom_input_style_note_message (8826731320846363423) --> + <skip /> + <!-- no translation found for enable (5031294444630523247) --> + <skip /> + <!-- no translation found for not_now (6172462888202790482) --> + <skip /> + <!-- no translation found for custom_input_style_already_exists (8008728952215449707) --> + <skip /> + <!-- no translation found for prefs_usability_study_mode (1261130555134595254) --> + <skip /> + <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) --> + <skip /> + <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) --> + <skip /> + <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) --> + <skip /> + <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) --> + <skip /> + <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) --> + <skip /> + <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) --> + <skip /> + <!-- no translation found for read_external_dictionary_confirm_install_message (6898610163768980870) --> + <skip /> + <!-- no translation found for error (8940763624668513648) --> + <skip /> + <!-- no translation found for button_default (3988017840431881491) --> + <skip /> + <!-- no translation found for setup_welcome_title (6112821709832031715) --> + <skip /> + <!-- no translation found for setup_welcome_additional_description (8150252008545768953) --> + <skip /> + <!-- no translation found for setup_start_action (8936036460897347708) --> + <skip /> + <!-- no translation found for setup_next_action (371821437915144603) --> + <skip /> + <!-- no translation found for setup_steps_title (6400373034871816182) --> + <skip /> + <!-- no translation found for setup_step1_title (3147967630253462315) --> + <skip /> + <!-- no translation found for setup_step1_instruction (2578631936624637241) --> + <skip /> + <!-- no translation found for setup_step1_finished_instruction (10761482004957994) --> + <skip /> + <!-- no translation found for setup_step1_action (4366513534999901728) --> + <skip /> + <!-- no translation found for setup_step2_title (6860725447906690594) --> + <skip /> + <!-- no translation found for setup_step2_instruction (9141481964870023336) --> + <skip /> + <!-- no translation found for setup_step2_action (1660330307159824337) --> + <skip /> + <!-- no translation found for setup_step3_title (3154757183631490281) --> + <skip /> + <!-- no translation found for setup_step3_instruction (8025981829605426000) --> + <skip /> + <!-- no translation found for setup_step3_action (600879797256942259) --> + <skip /> + <!-- no translation found for setup_finish_action (276559243409465389) --> + <skip /> + <!-- no translation found for show_setup_wizard_icon (5008028590593710830) --> + <skip /> + <!-- no translation found for show_setup_wizard_icon_summary (4119998322536880213) --> + <skip /> + <!-- no translation found for app_name (6320102637491234792) --> + <skip /> + <!-- no translation found for dictionary_provider_name (3027315045397363079) --> + <skip /> + <!-- no translation found for dictionary_service_name (6237472350693511448) --> + <skip /> + <!-- no translation found for download_description (6014835283119198591) --> + <skip /> + <!-- no translation found for dictionary_settings_title (8091417676045693313) --> + <skip /> + <!-- no translation found for dictionary_install_over_metered_network_prompt (3587517870006332980) --> + <skip /> + <!-- no translation found for dictionary_settings_summary (5305694987799824349) --> + <skip /> + <!-- no translation found for user_dictionaries (3582332055892252845) --> + <skip /> + <!-- no translation found for default_user_dict_pref_name (1625055720489280530) --> + <skip /> + <!-- no translation found for dictionary_available (4728975345815214218) --> + <skip /> + <!-- no translation found for dictionary_downloading (2982650524622620983) --> + <skip /> + <!-- no translation found for dictionary_installed (8081558343559342962) --> + <skip /> + <!-- no translation found for dictionary_disabled (8950383219564621762) --> + <skip /> + <!-- no translation found for cannot_connect_to_dict_service (9216933695765732398) --> + <skip /> + <!-- no translation found for no_dictionaries_available (8039920716566132611) --> + <skip /> + <!-- no translation found for check_for_updates_now (8087688440916388581) --> + <skip /> + <!-- no translation found for last_update (730467549913588780) --> + <skip /> + <!-- no translation found for message_updating (4457761393932375219) --> + <skip /> + <!-- no translation found for message_loading (8689096636874758814) --> + <skip /> + <!-- no translation found for main_dict_description (3072821352793492143) --> + <skip /> + <!-- no translation found for cancel (6830980399865683324) --> + <skip /> + <!-- no translation found for install_dict (180852772562189365) --> + <skip /> + <!-- no translation found for cancel_download_dict (7843340278507019303) --> + <skip /> + <!-- no translation found for delete_dict (756853268088330054) --> + <skip /> + <!-- no translation found for should_download_over_metered_prompt (2878629598667658845) --> + <skip /> + <!-- no translation found for download_over_metered (1643065851159409546) --> + <skip /> + <!-- no translation found for do_not_download_over_metered (2176209579313941583) --> + <skip /> + <!-- no translation found for dict_available_notification_title (6514288591959117288) --> + <skip /> + <!-- no translation found for dict_available_notification_description (1075194169443163487) --> + <skip /> + <!-- no translation found for toast_downloading_suggestions (1313027353588566660) --> + <skip /> + <!-- no translation found for version_text (2715354215568469385) --> + <skip /> + <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) --> + <skip /> + <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) --> + <skip /> + <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) --> + <skip /> + <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) --> + <skip /> + <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) --> + <skip /> + <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) --> + <skip /> + <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) --> + <skip /> + <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) --> + <skip /> + <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) --> + <skip /> + <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) --> + <skip /> + <!-- no translation found for user_dict_settings_empty_text (558499587532668203) --> + <skip /> + <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) --> + <skip /> + <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) --> + <skip /> + <!-- no translation found for user_dict_settings_delete (110413335187193859) --> + <skip /> + <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) --> + <skip /> +</resources> diff --git a/java/res/values-it/strings-action-keys.xml b/java/res/values-it/strings-action-keys.xml new file mode 100644 index 000000000..ecf02f58c --- /dev/null +++ b/java/res/values-it/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Vai"</string> + <string name="label_next_key" msgid="362972844525672568">"Avanti"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Indietro"</string> + <string name="label_done_key" msgid="2441578748772529288">"Fine"</string> + <string name="label_send_key" msgid="2815056534433717444">"Invia"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Attesa"</string> +</resources> diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml index 6989643af..7dd9692b9 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> @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Anteprima mobile dinamica"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Visualizza la parola suggerita durante il gesto"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : parola salvata"</string> - <string name="label_go_key" msgid="1635148082137219148">"Vai"</string> - <string name="label_next_key" msgid="362972844525672568">"Avanti"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Indietro"</string> - <string name="label_done_key" msgid="2441578748772529288">"Fine"</string> - <string name="label_send_key" msgid="2815056534433717444">"Invia"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Attesa"</string> <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 +119,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-action-keys.xml b/java/res/values-iw/strings-action-keys.xml new file mode 100644 index 000000000..cfd6a7b4e --- /dev/null +++ b/java/res/values-iw/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-iw/strings-appname.xml b/java/res/values-iw/strings-appname.xml index 1a07c5492..fc040f9ff 100644 --- a/java/res/values-iw/strings-appname.xml +++ b/java/res/values-iw/strings-appname.xml @@ -20,8 +20,8 @@ <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> + <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-iw/strings.xml b/java/res/values-iw/strings.xml index b3ee01410..dd185af91 100644 --- a/java/res/values-iw/strings.xml +++ b/java/res/values-iw/strings.xml @@ -38,7 +38,7 @@ <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="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> @@ -74,24 +74,15 @@ <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_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_description_unknown" msgid="3197434010402179157">"קוד מקש %d"</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_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> @@ -107,9 +98,9 @@ <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_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> @@ -149,12 +140,12 @@ <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_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> @@ -219,9 +210,9 @@ <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/> אנו ממליצים <b>להוריד</b> את המילון ב<xliff:g id="LANGUAGE">%1$s</xliff:g> כדי לשפר את חוויית ההקלדה.<br/> <br/> ההורדה עשויה לארוך דקה או שתיים ב-3G. ייתכן שתחויב אם אין לך <b>תוכנית נתונים בלתי מוגבלת</b>.<br/> אם אינך בטוח איזו תוכנית נתונים יש לך, אנו ממליצים לחפש חיבור Wi-Fi כדי להתחיל בהורדה באופן אוטומטי.<br/> <br/> טיפ: ניתן להוריד ולהסיר מילונים ב<b>שפה וקלט</b> בתפריט <b>הגדרות</b> של המכשיר הנייד שלך."</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="should_download_over_metered_prompt" msgid="2878629598667658845">"לשפה הנבחרת במכשיר הנייד שלך יש מילון זמין.<br/> אנו ממליצים <b>להוריד</b> את המילון ב<xliff:g id="LANGUAGE">%1$s</xliff:g> כדי לשפר את חוויית ההקלדה.<br/> <br/> ההורדה עשויה לארוך דקה או שתיים ב-3G. ייתכן שתחויב אם אין לך <b>תוכנית נתונים בלתי מוגבלת</b>.<br/> אם אינך בטוח איזו תוכנית נתונים יש לך, אנו ממליצים לחפש חיבור Wi-Fi כדי להתחיל בהורדה באופן אוטומטי.<br/> <br/> טיפ: ניתן להוריד ולהסיר מילונים ב<b>שפה וקלט</b> בתפריט <b>הגדרות</b> של המכשיר הנייד שלך."</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> diff --git a/java/res/values-ja/strings-action-keys.xml b/java/res/values-ja/strings-action-keys.xml new file mode 100644 index 000000000..342dc9a4d --- /dev/null +++ b/java/res/values-ja/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml index 37f06377e..f7e51d320 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> @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-ka-rGE/strings-action-keys.xml new file mode 100644 index 000000000..13066ad8a --- /dev/null +++ b/java/res/values-ka-rGE/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml index 193f5115d..71ed65783 100644 --- a/java/res/values-ka-rGE/strings.xml +++ b/java/res/values-ka-rGE/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-kk/strings-action-keys.xml b/java/res/values-kk/strings-action-keys.xml new file mode 100644 index 000000000..95c84a2ca --- /dev/null +++ b/java/res/values-kk/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-kk/strings.xml b/java/res/values-kk/strings.xml new file mode 100644 index 000000000..947ff2fe9 --- /dev/null +++ b/java/res/values-kk/strings.xml @@ -0,0 +1,243 @@ +<?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="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 (8005997889020109763) --> + <skip /> + <!-- 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">"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">"Негізгі пернетақтадағы Mic"</string> + <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Таңбалар пернетақтасындағы Mic"</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> + <!-- no translation found for subtype_nepali_traditional (9032247506728040447) --> + <skip /> + <string name="subtype_no_language" msgid="7137390094240139495">"Тіл жоқ (әліпби)"</string> + <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Әліпби (QWERTY)"</string> + <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Әліпби (QWERTZ)"</string> + <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> + <!-- no translation found for subtype_emoji (7483586578074549196) --> + <skip /> + <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">"Ұялы құрылғыдағы таңдалған тілде қолжетімді сөздік бар.<br/> Теру тәжірибесін арттыру үшін <xliff:g id="LANGUAGE">%1$s</xliff:g> сөздігін <b>жүктеп алуды</b> ұсынамыз.<br/> <br/> Жүктеп алу 3G арқылы бір немесе екі минут алуы мүмкін. Егер <b>шектеусіз деректер жоспары</b> болмаса, қосымша төлем алынуы мүмкін.<br/> Егер қай дерек жоспарына ие екеніңізді білмесеңіз, жүктеп алуды автоматты түрде бастау үшін Wi-Fi байланысын табуды ұсынамыз.<br/> <br/> Кеңес: Ұялы құрылғының <b>Параметрлер</b> мәзіріндегі <b>Тіл & енгізу</b> параметріне өту арқылы сөздіктерді жүктеп алуға және жоюға болады."</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">"Тіл:"</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-km-rKH/strings-action-keys.xml b/java/res/values-km-rKH/strings-action-keys.xml new file mode 100644 index 000000000..e90fba8bc --- /dev/null +++ b/java/res/values-km-rKH/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> 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..b9cd32da6 --- /dev/null +++ b/java/res/values-km-rKH/strings.xml @@ -0,0 +1,239 @@ +<?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="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>\" នៅក្នុងការកំណត់ភាសា & និងការបញ្ចូលរបស់អ្នក។ វានឹងដំណើរការនៅលើឧបករណ៍របស់អ្នក។"</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">"ភាសាដែលបានជ្រើសនៅលើឧបករណ៍របស់អ្នកមានវចនានុក្រម។ <br/> យើងបានផ្ដល់អនុសាសន៍ <b>ទាញយក</b> <xliff:g id="LANGUAGE">%1$s</xliff:g> វចនានុក្រម ដើម្បីធ្វើឲ្យការវាយបញ្ចូលរបស់អ្នកប្រសើរឡើង។ <br/> <br/> ការទាញយកអាចចំណាយពេលមួយ ឬពីរនាទីតាម 3G ។ ការកាត់លុយអាចអនុវត្ត ប្រសិនបើអ្នកបាន <b>កំណត់ទិន្នន័យគ្មានដែនកំណត់ </b>.<br/> ប្រសិនបើអ្នកមិនប្រាកដថាទិន្នន័យអ្នកមិនបានកំណត់ យើងបានផ្ដល់អនុសាសន៍ដោយស្វែងរកការភ្ជាប់វ៉ាយហ្វាយ ដើម្បីចាប់ផ្ដើមទាញយកដោយស្វ័យប្រវត្តិ។<br/> <br/> ព័ត៌មានជំនួយ៖ អ្នកអាចទាញយក និងលុបវចនានុក្រមដោយចូលទៅ <b>ភាសា& បញ្ចូល</b>នៅក្នុងម៉ឺនុយ <b>ការកំណត់ </b> របស់ឧបករណ៍ចល័ត។"</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-action-keys.xml b/java/res/values-ko/strings-action-keys.xml new file mode 100644 index 000000000..42991242b --- /dev/null +++ b/java/res/values-ko/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml index 1497812e9..259a142dd 100644 --- a/java/res/values-ko/strings.xml +++ b/java/res/values-ko/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-ky/strings-action-keys.xml b/java/res/values-ky/strings-action-keys.xml new file mode 100644 index 000000000..5eda61e1b --- /dev/null +++ b/java/res/values-ky/strings-action-keys.xml @@ -0,0 +1,31 @@ +<?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:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Баруу"</string> + <string name="label_next_key" msgid="362972844525672568">"Кийин"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Мурун"</string> + <string name="label_done_key" msgid="2441578748772529288">"Даяр"</string> + <string name="label_send_key" msgid="2815056534433717444">"Жибер"</string> + <!-- no translation found for label_pause_key (181098308428035340) --> + <skip /> + <!-- no translation found for label_wait_key (6402152600878093134) --> + <skip /> +</resources> diff --git a/java/res/values-ky/strings.xml b/java/res/values-ky/strings.xml index 45d855cf6..e30c4b965 100644 --- a/java/res/values-ky/strings.xml +++ b/java/res/values-ky/strings.xml @@ -112,19 +112,10 @@ <skip /> <!-- no translation found for added_word (8993883354622484372) --> <skip /> - <string name="label_go_key" msgid="1635148082137219148">"Баруу"</string> - <string name="label_next_key" msgid="362972844525672568">"Кийин"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Мурун"</string> - <string name="label_done_key" msgid="2441578748772529288">"Даяр"</string> - <string name="label_send_key" msgid="2815056534433717444">"Жибер"</string> <!-- no translation found for label_to_symbol_key (8516904117128967293) --> <skip /> <!-- no translation found for label_to_symbol_with_microphone_key (9035925553010061906) --> <skip /> - <!-- no translation found for label_pause_key (181098308428035340) --> - <skip /> - <!-- no translation found for label_wait_key (6402152600878093134) --> - <skip /> <!-- no translation found for spoken_use_headphones (896961781287283493) --> <skip /> <!-- no translation found for spoken_current_text_is (2485723011272583845) --> diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml index b874d4881..c97e68f11 100644 --- a/java/res/values-land/dimens.xml +++ b/java/res/values-land/dimens.xml @@ -31,10 +31,10 @@ <fraction name="key_bottom_gap_gb">5.941%p</fraction> <fraction name="key_horizontal_gap_gb">0.997%p</fraction> - <fraction name="keyboard_top_padding_ics">2.727%p</fraction> - <fraction name="keyboard_bottom_padding_ics">0.0%p</fraction> - <fraction name="key_bottom_gap_ics">5.368%p</fraction> - <fraction name="key_horizontal_gap_ics">1.020%p</fraction> + <fraction name="keyboard_top_padding_holo">2.727%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">5.368%p</fraction> + <fraction name="key_horizontal_gap_holo">1.020%p</fraction> <!-- left or right padding of label alignment --> <dimen name="key_label_horizontal_padding">8dp</dimen> @@ -54,9 +54,9 @@ <fraction name="key_letter_ratio_5row">78%</fraction> <fraction name="key_uppercase_letter_ratio_5row">48%</fraction> - <dimen name="key_preview_offset_ics">1.6dp</dimen> + <dimen name="key_preview_offset_holo">1.6dp</dimen> <!-- popup_key_height x -0.5 --> - <dimen name="more_keys_keyboard_vertical_correction_ics">-22.4dp</dimen> + <dimen name="more_keys_keyboard_vertical_correction_holo">-22.4dp</dimen> <dimen name="suggestions_strip_height">36dp</dimen> <dimen name="more_suggestions_row_height">36dp</dimen> diff --git a/java/res/values-lo-rLA/strings-action-keys.xml b/java/res/values-lo-rLA/strings-action-keys.xml new file mode 100644 index 000000000..8cb6a241f --- /dev/null +++ b/java/res/values-lo-rLA/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> 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..b1b02cce7 --- /dev/null +++ b/java/res/values-lo-rLA/strings.xml @@ -0,0 +1,239 @@ +<?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="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>\" ໃນການຕັ້ງຄ່າພາສາ & ການປ້ອນຂໍ້ມູນຂອງທ່ານ. ນີ້ຈະເປັນການອະນຸຍາດໃຫ້ມັນເຮັດວຽກໃນອຸປະກອນຂອງທ່ານ"</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">"ສະແດງໄອຄອນຂອງແອັບຯໃນ 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">"ພາສາທີ່ທ່ານເລືອກໃຊ້ໃນອຸປະກອນຂອງທ່ານນັ້ນ ມີວັດຈະນານຸກົມໃຫ້ໃຊ້ພ້ອມ.<br/> ພວກເຮົາແນະນຳໃຫ້ <b>ດາວໂຫລດ</b> <xliff:g id="LANGUAGE">%1$s</xliff:g> ວັດຈະນານຸກົມດັ່ງກ່າວ ເພື່ອເພີ່ມປະສົບການໃນການພິມຂອງທ່ານ.<br/> <br/> ການດາວໂຫລດອາດຈະໃຊ້ເວລາພຽງໜຶ່ງເຖິງສອງນາທີ ໂດຍການໃຊ້ 3G. ທ່ານອາດຈະເສຍຄ່າບໍລິການສຳລັບອິນເຕີເນັດ ຫາກທ່ານບໍ່ມີ <b>ການນຳໃຊ້ອິນເຕີເນັດແບບບໍ່ຈຳກັດ</b>.<br/> ຫາກທ່ານບໍ່ແນ່ໃຈວ່າຮູບແບບການໃຊ້ໃດທີ່ທ່ານມີຢູ່ ພວກເຮົາແນະນຳໃຫ້ຊອກຫາການເຊື່ອມຕໍ່ Wi-Fi ເພື່ອດາວໂຫລດມັນໂດຍອັດຕະໂນມັດ.<br/> <br/> ເຄັດລັບ: ທ່ານສາມາດດາວໂຫລດ ແລະ ລຶບວັດຈະນານຸກົມໄດ້ທີ່ <b>ພາສາ & ການປ້ອນຂໍ້ມູນ</b> ຢູ່ໃນເມນູ <b>ການຕັ້ງຄ່າ</b> ຂອງອຸປະກອນພົກພາຂອງທ່ານ."</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-action-keys.xml b/java/res/values-lt/strings-action-keys.xml new file mode 100644 index 000000000..c1309b75c --- /dev/null +++ b/java/res/values-lt/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Pradėti"</string> + <string name="label_next_key" msgid="362972844525672568">"Kitas"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Anks."</string> + <string name="label_done_key" msgid="2441578748772529288">"Atlikta"</string> + <string name="label_send_key" msgid="2815056534433717444">"Siųsti"</string> + <string name="label_pause_key" msgid="181098308428035340">"Prist."</string> + <string name="label_wait_key" msgid="6402152600878093134">"Lauk."</string> +</resources> diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml index 88328db7d..4a6daab8b 100644 --- a/java/res/values-lt/strings.xml +++ b/java/res/values-lt/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dinaminė slankioji peržiūra"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Gestikuliuojant peržiūrėti siūlomą žodį"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: išsaugota"</string> - <string name="label_go_key" msgid="1635148082137219148">"Pradėti"</string> - <string name="label_next_key" msgid="362972844525672568">"Kitas"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Anks."</string> - <string name="label_done_key" msgid="2441578748772529288">"Atlikta"</string> - <string name="label_send_key" msgid="2815056534433717444">"Siųsti"</string> - <string name="label_pause_key" msgid="181098308428035340">"Prist."</string> - <string name="label_wait_key" msgid="6402152600878093134">"Lauk."</string> <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-action-keys.xml b/java/res/values-lv/strings-action-keys.xml new file mode 100644 index 000000000..d6750d02a --- /dev/null +++ b/java/res/values-lv/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Sākt"</string> + <string name="label_next_key" msgid="362972844525672568">"Tālāk"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Iepr."</string> + <string name="label_done_key" msgid="2441578748772529288">"Gatavs"</string> + <string name="label_send_key" msgid="2815056534433717444">"Sūtīt"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pauze"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Gaidīt"</string> +</resources> diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml index 069c48701..5770c2959 100644 --- a/java/res/values-lv/strings.xml +++ b/java/res/values-lv/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dinamisk. peldošais priekšsk."</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Skatiet ieteikto vārdu, veicot žestu."</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: saglabāts"</string> - <string name="label_go_key" msgid="1635148082137219148">"Sākt"</string> - <string name="label_next_key" msgid="362972844525672568">"Tālāk"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Iepr."</string> - <string name="label_done_key" msgid="2441578748772529288">"Gatavs"</string> - <string name="label_send_key" msgid="2815056534433717444">"Sūtīt"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pauze"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Gaidīt"</string> <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-mk/strings-action-keys.xml b/java/res/values-mk/strings-action-keys.xml new file mode 100644 index 000000000..40de51b00 --- /dev/null +++ b/java/res/values-mk/strings-action-keys.xml @@ -0,0 +1,31 @@ +<?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:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Оди"</string> + <string name="label_next_key" msgid="362972844525672568">"Следно"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Претходно"</string> + <string name="label_done_key" msgid="2441578748772529288">"Готово"</string> + <string name="label_send_key" msgid="2815056534433717444">"Испрати"</string> + <!-- no translation found for label_pause_key (181098308428035340) --> + <skip /> + <!-- no translation found for label_wait_key (6402152600878093134) --> + <skip /> +</resources> diff --git a/java/res/values-mk/strings.xml b/java/res/values-mk/strings.xml new file mode 100644 index 000000000..6f685d395 --- /dev/null +++ b/java/res/values-mk/strings.xml @@ -0,0 +1,455 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- no translation found for english_ime_input_options (3909945612939668554) --> + <skip /> + <!-- no translation found for english_ime_research_log (8492602295696577851) --> + <skip /> + <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) --> + <skip /> + <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) --> + <skip /> + <!-- no translation found for vibrate_on_keypress (5258079494276955460) --> + <skip /> + <!-- no translation found for sound_on_keypress (6093592297198243644) --> + <skip /> + <!-- no translation found for popup_on_keypress (123894815723512944) --> + <skip /> + <!-- no translation found for general_category (1859088467017573195) --> + <skip /> + <!-- no translation found for correction_category (2236750915056607613) --> + <skip /> + <!-- no translation found for gesture_typing_category (497263612130532630) --> + <skip /> + <!-- no translation found for misc_category (6894192814868233453) --> + <skip /> + <!-- no translation found for advanced_settings (362895144495591463) --> + <skip /> + <!-- no translation found for advanced_settings_summary (4487980456152830271) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for show_language_switch_key (5915478828318774384) --> + <skip /> + <!-- no translation found for show_language_switch_key_summary (7343403647474265713) --> + <skip /> + <!-- no translation found for sliding_key_input_preview (6604262359510068370) --> + <skip /> + <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) --> + <skip /> + <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) --> + <skip /> + <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) --> + <skip /> + <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) --> + <skip /> + <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) --> + <skip /> + <!-- no translation found for settings_system_default (6268225104743331821) --> + <skip /> + <!-- no translation found for use_contacts_dict (4435317977804180815) --> + <skip /> + <!-- no translation found for use_contacts_dict_summary (6599983334507879959) --> + <skip /> + <!-- no translation found for use_double_space_period (8781529969425082860) --> + <skip /> + <!-- no translation found for use_double_space_period_summary (6532892187247952799) --> + <skip /> + <!-- no translation found for auto_cap (1719746674854628252) --> + <skip /> + <!-- no translation found for auto_cap_summary (7934452761022946874) --> + <skip /> + <!-- no translation found for edit_personal_dictionary (3996910038952940420) --> + <skip /> + <!-- no translation found for configure_dictionaries_title (4238652338556902049) --> + <skip /> + <!-- no translation found for main_dictionary (4798763781818361168) --> + <skip /> + <!-- no translation found for prefs_show_suggestions (8026799663445531637) --> + <skip /> + <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) --> + <skip /> + <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) --> + <skip /> + <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) --> + <skip /> + <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) --> + <skip /> + <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) --> + <skip /> + <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) --> + <skip /> + <!-- no translation found for auto_correction (7630720885194996950) --> + <skip /> + <!-- no translation found for auto_correction_summary (5625751551134658006) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) --> + <skip /> + <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) --> + <skip /> + <!-- no translation found for bigram_prediction (1084449187723948550) --> + <skip /> + <!-- no translation found for bigram_prediction_summary (3896362682751109677) --> + <skip /> + <!-- no translation found for gesture_input (826951152254563827) --> + <skip /> + <!-- no translation found for gesture_input_summary (9180350639305731231) --> + <skip /> + <!-- no translation found for gesture_preview_trail (3802333369335722221) --> + <skip /> + <!-- no translation found for gesture_floating_preview_text (4443240334739381053) --> + <skip /> + <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) --> + <skip /> + <!-- no translation found for added_word (8993883354622484372) --> + <skip /> + <!-- no translation found for spoken_use_headphones (896961781287283493) --> + <skip /> + <!-- no translation found for spoken_current_text_is (2485723011272583845) --> + <skip /> + <!-- no translation found for spoken_no_text_entered (7479685225597344496) --> + <skip /> + <!-- no translation found for spoken_auto_correct (8005997889020109763) --> + <skip /> + <!-- no translation found for spoken_auto_correct_obscured (6276420476908833791) --> + <skip /> + <!-- no translation found for spoken_description_unknown (3197434010402179157) --> + <skip /> + <!-- no translation found for spoken_description_shift (244197883292549308) --> + <skip /> + <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) --> + <skip /> + <!-- no translation found for spoken_description_caps_lock (3276478269526304432) --> + <skip /> + <!-- no translation found for spoken_description_delete (8740376944276199801) --> + <skip /> + <!-- no translation found for spoken_description_to_symbol (5486340107500448969) --> + <skip /> + <!-- no translation found for spoken_description_to_alpha (23129338819771807) --> + <skip /> + <!-- no translation found for spoken_description_to_numeric (591752092685161732) --> + <skip /> + <!-- no translation found for spoken_description_settings (4627462689603838099) --> + <skip /> + <!-- no translation found for spoken_description_tab (2667716002663482248) --> + <skip /> + <!-- no translation found for spoken_description_space (2582521050049860859) --> + <skip /> + <!-- no translation found for spoken_description_mic (615536748882611950) --> + <skip /> + <!-- no translation found for spoken_description_smiley (2256309826200113918) --> + <skip /> + <!-- no translation found for spoken_description_return (8178083177238315647) --> + <skip /> + <!-- no translation found for spoken_description_search (1247236163755920808) --> + <skip /> + <!-- no translation found for spoken_description_dot (40711082435231673) --> + <skip /> + <!-- no translation found for spoken_description_language_switch (5507091328222331316) --> + <skip /> + <!-- no translation found for spoken_description_action_next (8636078276664150324) --> + <skip /> + <!-- no translation found for spoken_description_action_previous (800872415009336208) --> + <skip /> + <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) --> + <skip /> + <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) --> + <skip /> + <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) --> + <skip /> + <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) --> + <skip /> + <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) --> + <skip /> + <!-- no translation found for spoken_description_mode_phone (6520207943132026264) --> + <skip /> + <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) --> + <skip /> + <!-- no translation found for announce_keyboard_hidden (8718927835531429807) --> + <skip /> + <!-- no translation found for announce_keyboard_mode (4729081055438508321) --> + <skip /> + <!-- no translation found for keyboard_mode_date (3137520166817128102) --> + <skip /> + <!-- no translation found for keyboard_mode_date_time (339593358488851072) --> + <skip /> + <!-- no translation found for keyboard_mode_email (6216248078128294262) --> + <skip /> + <!-- no translation found for keyboard_mode_im (1137405089766557048) --> + <skip /> + <!-- no translation found for keyboard_mode_number (7991623440699957069) --> + <skip /> + <!-- no translation found for keyboard_mode_phone (6851627527401433229) --> + <skip /> + <!-- no translation found for keyboard_mode_text (6479436687899701619) --> + <skip /> + <!-- no translation found for keyboard_mode_time (4381856885582143277) --> + <skip /> + <!-- no translation found for keyboard_mode_url (1519819835514911218) --> + <skip /> + <!-- no translation found for voice_input (3583258583521397548) --> + <skip /> + <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> + <skip /> + <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) --> + <skip /> + <!-- no translation found for voice_input_modes_off (3745699748218082014) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_main_keyboard (6586544292900314339) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_symbols_keyboard (5233725927281932391) --> + <skip /> + <!-- no translation found for voice_input_modes_summary_off (63875609591897607) --> + <skip /> + <!-- no translation found for configure_input_method (373356270290742459) --> + <skip /> + <!-- no translation found for language_selection_title (1651299598555326750) --> + <skip /> + <!-- no translation found for send_feedback (1780431884109392046) --> + <skip /> + <!-- no translation found for select_language (3693815588777926848) --> + <skip /> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> + <!-- no translation found for has_dictionary (6071847973466625007) --> + <skip /> + <!-- no translation found for prefs_enable_log (6620424505072963557) --> + <skip /> + <!-- no translation found for prefs_description_log (7525225584555429211) --> + <skip /> + <!-- no translation found for keyboard_layout (8451164783510487501) --> + <skip /> + <!-- no translation found for subtype_en_GB (88170601942311355) --> + <skip /> + <!-- no translation found for subtype_en_US (6160452336634534239) --> + <skip /> + <!-- no translation found for subtype_es_US (5583145191430180200) --> + <skip /> + <!-- no translation found for subtype_with_layout_en_GB (2179097748724725906) --> + <skip /> + <!-- no translation found for subtype_with_layout_en_US (1362581347576714579) --> + <skip /> + <!-- no translation found for subtype_with_layout_es_US (6261791057007890189) --> + <skip /> + <!-- no translation found for subtype_nepali_traditional (9032247506728040447) --> + <skip /> + <!-- no translation found for subtype_no_language (7137390094240139495) --> + <skip /> + <!-- no translation found for subtype_no_language_qwerty (244337630616742604) --> + <skip /> + <!-- no translation found for subtype_no_language_qwertz (443066912507547976) --> + <skip /> + <!-- no translation found for subtype_no_language_azerty (8144348527575640087) --> + <skip /> + <!-- no translation found for subtype_no_language_dvorak (1564494667584718094) --> + <skip /> + <!-- no translation found for subtype_no_language_colemak (5837418400010302623) --> + <skip /> + <!-- no translation found for subtype_no_language_pcqwerty (5354918232046200018) --> + <skip /> + <!-- no translation found for subtype_emoji (7483586578074549196) --> + <skip /> + <!-- no translation found for custom_input_styles_title (8429952441821251512) --> + <skip /> + <!-- no translation found for add_style (6163126614514489951) --> + <skip /> + <!-- no translation found for add (8299699805688017798) --> + <skip /> + <!-- no translation found for remove (4486081658752944606) --> + <skip /> + <!-- no translation found for save (7646738597196767214) --> + <skip /> + <!-- no translation found for subtype_locale (8576443440738143764) --> + <skip /> + <!-- no translation found for keyboard_layout_set (4309233698194565609) --> + <skip /> + <!-- no translation found for custom_input_style_note_message (8826731320846363423) --> + <skip /> + <!-- no translation found for enable (5031294444630523247) --> + <skip /> + <!-- no translation found for not_now (6172462888202790482) --> + <skip /> + <!-- no translation found for custom_input_style_already_exists (8008728952215449707) --> + <skip /> + <!-- no translation found for prefs_usability_study_mode (1261130555134595254) --> + <skip /> + <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) --> + <skip /> + <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) --> + <skip /> + <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) --> + <skip /> + <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) --> + <skip /> + <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) --> + <skip /> + <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) --> + <skip /> + <!-- no translation found for read_external_dictionary_confirm_install_message (6898610163768980870) --> + <skip /> + <!-- no translation found for error (8940763624668513648) --> + <skip /> + <!-- no translation found for button_default (3988017840431881491) --> + <skip /> + <!-- no translation found for setup_welcome_title (6112821709832031715) --> + <skip /> + <!-- no translation found for setup_welcome_additional_description (8150252008545768953) --> + <skip /> + <!-- no translation found for setup_start_action (8936036460897347708) --> + <skip /> + <!-- no translation found for setup_next_action (371821437915144603) --> + <skip /> + <!-- no translation found for setup_steps_title (6400373034871816182) --> + <skip /> + <!-- no translation found for setup_step1_title (3147967630253462315) --> + <skip /> + <!-- no translation found for setup_step1_instruction (2578631936624637241) --> + <skip /> + <!-- no translation found for setup_step1_finished_instruction (10761482004957994) --> + <skip /> + <!-- no translation found for setup_step1_action (4366513534999901728) --> + <skip /> + <!-- no translation found for setup_step2_title (6860725447906690594) --> + <skip /> + <!-- no translation found for setup_step2_instruction (9141481964870023336) --> + <skip /> + <!-- no translation found for setup_step2_action (1660330307159824337) --> + <skip /> + <!-- no translation found for setup_step3_title (3154757183631490281) --> + <skip /> + <!-- no translation found for setup_step3_instruction (8025981829605426000) --> + <skip /> + <!-- no translation found for setup_step3_action (600879797256942259) --> + <skip /> + <!-- no translation found for setup_finish_action (276559243409465389) --> + <skip /> + <!-- no translation found for show_setup_wizard_icon (5008028590593710830) --> + <skip /> + <!-- no translation found for show_setup_wizard_icon_summary (4119998322536880213) --> + <skip /> + <!-- no translation found for app_name (6320102637491234792) --> + <skip /> + <!-- no translation found for dictionary_provider_name (3027315045397363079) --> + <skip /> + <!-- no translation found for dictionary_service_name (6237472350693511448) --> + <skip /> + <!-- no translation found for download_description (6014835283119198591) --> + <skip /> + <!-- no translation found for dictionary_settings_title (8091417676045693313) --> + <skip /> + <!-- no translation found for dictionary_install_over_metered_network_prompt (3587517870006332980) --> + <skip /> + <!-- no translation found for dictionary_settings_summary (5305694987799824349) --> + <skip /> + <!-- no translation found for user_dictionaries (3582332055892252845) --> + <skip /> + <!-- no translation found for default_user_dict_pref_name (1625055720489280530) --> + <skip /> + <!-- no translation found for dictionary_available (4728975345815214218) --> + <skip /> + <!-- no translation found for dictionary_downloading (2982650524622620983) --> + <skip /> + <!-- no translation found for dictionary_installed (8081558343559342962) --> + <skip /> + <!-- no translation found for dictionary_disabled (8950383219564621762) --> + <skip /> + <!-- no translation found for cannot_connect_to_dict_service (9216933695765732398) --> + <skip /> + <!-- no translation found for no_dictionaries_available (8039920716566132611) --> + <skip /> + <!-- no translation found for check_for_updates_now (8087688440916388581) --> + <skip /> + <!-- no translation found for last_update (730467549913588780) --> + <skip /> + <!-- no translation found for message_updating (4457761393932375219) --> + <skip /> + <!-- no translation found for message_loading (8689096636874758814) --> + <skip /> + <!-- no translation found for main_dict_description (3072821352793492143) --> + <skip /> + <!-- no translation found for cancel (6830980399865683324) --> + <skip /> + <!-- no translation found for install_dict (180852772562189365) --> + <skip /> + <!-- no translation found for cancel_download_dict (7843340278507019303) --> + <skip /> + <!-- no translation found for delete_dict (756853268088330054) --> + <skip /> + <!-- no translation found for should_download_over_metered_prompt (2878629598667658845) --> + <skip /> + <!-- no translation found for download_over_metered (1643065851159409546) --> + <skip /> + <!-- no translation found for do_not_download_over_metered (2176209579313941583) --> + <skip /> + <!-- no translation found for dict_available_notification_title (6514288591959117288) --> + <skip /> + <!-- no translation found for dict_available_notification_description (1075194169443163487) --> + <skip /> + <!-- no translation found for toast_downloading_suggestions (1313027353588566660) --> + <skip /> + <!-- no translation found for version_text (2715354215568469385) --> + <skip /> + <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) --> + <skip /> + <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) --> + <skip /> + <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) --> + <skip /> + <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) --> + <skip /> + <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) --> + <skip /> + <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) --> + <skip /> + <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) --> + <skip /> + <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) --> + <skip /> + <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) --> + <skip /> + <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) --> + <skip /> + <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) --> + <skip /> + <!-- no translation found for user_dict_settings_empty_text (558499587532668203) --> + <skip /> + <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) --> + <skip /> + <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) --> + <skip /> + <!-- no translation found for user_dict_settings_delete (110413335187193859) --> + <skip /> + <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) --> + <skip /> +</resources> diff --git a/java/res/values-mn-rMN/strings-action-keys.xml b/java/res/values-mn-rMN/strings-action-keys.xml new file mode 100644 index 000000000..7cf345e7c --- /dev/null +++ b/java/res/values-mn-rMN/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml index 3b039f120..658f6d8af 100644 --- a/java/res/values-mn-rMN/strings.xml +++ b/java/res/values-mn-rMN/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-ms-rMY/strings-action-keys.xml new file mode 100644 index 000000000..5f14b84ec --- /dev/null +++ b/java/res/values-ms-rMY/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Pergi"</string> + <string name="label_next_key" msgid="362972844525672568">"Seterusnya"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Sblm"</string> + <string name="label_done_key" msgid="2441578748772529288">"Selesai"</string> + <string name="label_send_key" msgid="2815056534433717444">"Hantar"</string> + <string name="label_pause_key" msgid="181098308428035340">"Jeda"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Tunggu"</string> +</resources> diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml index ee241d64b..a87454891 100644 --- a/java/res/values-ms-rMY/strings.xml +++ b/java/res/values-ms-rMY/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Pratonton terapung dinamik"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Lihat perkataan yang dicadangkan semasa membuat gerak isyarat"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Disimpan"</string> - <string name="label_go_key" msgid="1635148082137219148">"Pergi"</string> - <string name="label_next_key" msgid="362972844525672568">"Seterusnya"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Sblm"</string> - <string name="label_done_key" msgid="2441578748772529288">"Selesai"</string> - <string name="label_send_key" msgid="2815056534433717444">"Hantar"</string> - <string name="label_pause_key" msgid="181098308428035340">"Jeda"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Tunggu"</string> <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-action-keys.xml b/java/res/values-nb/strings-action-keys.xml new file mode 100644 index 000000000..840e8c842 --- /dev/null +++ b/java/res/values-nb/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Utfør"</string> + <string name="label_next_key" msgid="362972844525672568">"Neste"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Forr."</string> + <string name="label_done_key" msgid="2441578748772529288">"Utfør"</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">"Vent"</string> +</resources> diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index ae43d1078..500fc3301 100644 --- a/java/res/values-nb/strings.xml +++ b/java/res/values-nb/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamisk flytende forhåndsvsn."</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Se det foreslåtte ordet mens du utfører bevegelser"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Lagret"</string> - <string name="label_go_key" msgid="1635148082137219148">"Utfør"</string> - <string name="label_next_key" msgid="362972844525672568">"Neste"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Forr."</string> - <string name="label_done_key" msgid="2441578748772529288">"Utfør"</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">"Vent"</string> <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 +215,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-action-keys.xml b/java/res/values-nl/strings-action-keys.xml new file mode 100644 index 000000000..3a6967fc2 --- /dev/null +++ b/java/res/values-nl/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Start"</string> + <string name="label_next_key" msgid="362972844525672568">"Verder"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Vorig"</string> + <string name="label_done_key" msgid="2441578748772529288">"Gereed"</string> + <string name="label_send_key" msgid="2815056534433717444">"Zenden"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pauze"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Wacht"</string> +</resources> diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml index de20da4f8..4413b273d 100644 --- a/java/res/values-nl/strings.xml +++ b/java/res/values-nl/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamisch zwevend voorbeeld"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Het voorgestelde woord weergeven tijdens het tekenen"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: opgeslagen"</string> - <string name="label_go_key" msgid="1635148082137219148">"Start"</string> - <string name="label_next_key" msgid="362972844525672568">"Verder"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Vorig"</string> - <string name="label_done_key" msgid="2441578748772529288">"Gereed"</string> - <string name="label_send_key" msgid="2815056534433717444">"Zenden"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pauze"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Wacht"</string> <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-action-keys.xml b/java/res/values-pl/strings-action-keys.xml new file mode 100644 index 000000000..4bbceeacf --- /dev/null +++ b/java/res/values-pl/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"OK"</string> + <string name="label_next_key" msgid="362972844525672568">"Dalej"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Wstecz"</string> + <string name="label_done_key" msgid="2441578748772529288">"OK"</string> + <string name="label_send_key" msgid="2815056534433717444">"Wyślij"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pauza"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Czekaj"</string> +</resources> diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml index 390837596..d36cd49ba 100644 --- a/java/res/values-pl/strings.xml +++ b/java/res/values-pl/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamiczny podgląd słowa"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Podczas gestykulacji będzie widoczne podpowiadane słowo"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Zapisano"</string> - <string name="label_go_key" msgid="1635148082137219148">"OK"</string> - <string name="label_next_key" msgid="362972844525672568">"Dalej"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Wstecz"</string> - <string name="label_done_key" msgid="2441578748772529288">"OK"</string> - <string name="label_send_key" msgid="2815056534433717444">"Wyślij"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pauza"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Czekaj"</string> <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-action-keys.xml b/java/res/values-pt-rPT/strings-action-keys.xml new file mode 100644 index 000000000..88d9ceb9b --- /dev/null +++ b/java/res/values-pt-rPT/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> + <string name="label_next_key" msgid="362972844525672568">"Avançar"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> + <string name="label_done_key" msgid="2441578748772529288">"OK"</string> + <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Esp."</string> +</resources> diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml index 4c81479e5..c7eb06563 100644 --- a/java/res/values-pt-rPT/strings.xml +++ b/java/res/values-pt-rPT/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Pré-visual. flutuante dinâmica"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Ver palavra sugerida enquanto toca"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string> - <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> - <string name="label_next_key" msgid="362972844525672568">"Avançar"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> - <string name="label_done_key" msgid="2441578748772529288">"OK"</string> - <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Esp."</string> <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-action-keys.xml b/java/res/values-pt/strings-action-keys.xml new file mode 100644 index 000000000..e007dc009 --- /dev/null +++ b/java/res/values-pt/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> + <string name="label_next_key" msgid="362972844525672568">"Avançar"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Volt."</string> + <string name="label_done_key" msgid="2441578748772529288">"Feito"</string> + <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Esp."</string> +</resources> diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml index ef533ae83..2aa7f7739 100644 --- a/java/res/values-pt/strings.xml +++ b/java/res/values-pt/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Visualizaç. dinâmica flutuante"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Ver a palavra sugerida ao usar gestos"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Salvo"</string> - <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> - <string name="label_next_key" msgid="362972844525672568">"Avançar"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Volt."</string> - <string name="label_done_key" msgid="2441578748772529288">"Feito"</string> - <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Esp."</string> <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-action-keys.xml b/java/res/values-rm/strings-action-keys.xml new file mode 100644 index 000000000..fbe84b573 --- /dev/null +++ b/java/res/values-rm/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Dai"</string> + <string name="label_next_key" msgid="362972844525672568">"Vinavant"</string> + <!-- no translation found for label_previous_key (1211868118071386787) --> + <skip /> + <string name="label_done_key" msgid="2441578748772529288">"Finì"</string> + <string name="label_send_key" msgid="2815056534433717444">"Trametter"</string> + <!-- no translation found for label_pause_key (181098308428035340) --> + <skip /> + <!-- no translation found for label_wait_key (6402152600878093134) --> + <skip /> +</resources> diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml index c68d30c0c..3f0bab963 100644 --- a/java/res/values-rm/strings.xml +++ b/java/res/values-rm/strings.xml @@ -123,25 +123,15 @@ <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) --> <skip /> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Memorisà"</string> - <string name="label_go_key" msgid="1635148082137219148">"Dai"</string> - <string name="label_next_key" msgid="362972844525672568">"Vinavant"</string> - <!-- no translation found for label_previous_key (1211868118071386787) --> - <skip /> - <string name="label_done_key" msgid="2441578748772529288">"Finì"</string> - <string name="label_send_key" msgid="2815056534433717444">"Trametter"</string> - <!-- no translation found for label_pause_key (181098308428035340) --> - <skip /> - <!-- no translation found for label_wait_key (6402152600878093134) --> - <skip /> <!-- no translation found for spoken_use_headphones (896961781287283493) --> <skip /> <!-- no translation found for spoken_current_text_is (2485723011272583845) --> <skip /> <!-- no translation found for spoken_no_text_entered (7479685225597344496) --> <skip /> - <!-- no translation found for spoken_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-action-keys.xml b/java/res/values-ro/strings-action-keys.xml new file mode 100644 index 000000000..cdb913452 --- /dev/null +++ b/java/res/values-ro/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"OK"</string> + <string name="label_next_key" msgid="362972844525672568">"Înainte"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Înapoi"</string> + <string name="label_done_key" msgid="2441578748772529288">"Terminat"</string> + <string name="label_send_key" msgid="2815056534433717444">"Trimiteţi"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pauză"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Aşt."</string> +</resources> diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml index 930b68bd6..ad4456aad 100644 --- a/java/res/values-ro/strings.xml +++ b/java/res/values-ro/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Sugestie flotantă dinamică"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Afişaţi cuvântul sugerat când utilizaţi gesturi"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: salvat"</string> - <string name="label_go_key" msgid="1635148082137219148">"OK"</string> - <string name="label_next_key" msgid="362972844525672568">"Înainte"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Înapoi"</string> - <string name="label_done_key" msgid="2441578748772529288">"Terminat"</string> - <string name="label_send_key" msgid="2815056534433717444">"Trimiteţi"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pauză"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Aşt."</string> <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-action-keys.xml b/java/res/values-ru/strings-action-keys.xml new file mode 100644 index 000000000..331d28c6b --- /dev/null +++ b/java/res/values-ru/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml index 8bfb011c5..6db65e9ba 100644 --- a/java/res/values-ru/strings.xml +++ b/java/res/values-ru/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-sk/strings-action-keys.xml new file mode 100644 index 000000000..a646663d6 --- /dev/null +++ b/java/res/values-sk/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Hľadať"</string> + <string name="label_next_key" msgid="362972844525672568">"Ďalej"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Pred."</string> + <string name="label_done_key" msgid="2441578748772529288">"Hotovo"</string> + <string name="label_send_key" msgid="2815056534433717444">"Odoslať"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pozastaviť"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Čakajte"</string> +</resources> diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml index 5c25f28ce..9e5de1e89 100644 --- a/java/res/values-sk/strings.xml +++ b/java/res/values-sk/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamická plávajúca ukážka"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Zobrazenie navrhovaného slova pri písaní gestami"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Uložené"</string> - <string name="label_go_key" msgid="1635148082137219148">"Hľadať"</string> - <string name="label_next_key" msgid="362972844525672568">"Ďalej"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Pred."</string> - <string name="label_done_key" msgid="2441578748772529288">"Hotovo"</string> - <string name="label_send_key" msgid="2815056534433717444">"Odoslať"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pozastaviť"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Čakajte"</string> <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-action-keys.xml b/java/res/values-sl/strings-action-keys.xml new file mode 100644 index 000000000..7e6c7787e --- /dev/null +++ b/java/res/values-sl/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Pojdi"</string> + <string name="label_next_key" msgid="362972844525672568">"Naprej"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Nazaj"</string> + <string name="label_done_key" msgid="2441578748772529288">"Dokončano"</string> + <string name="label_send_key" msgid="2815056534433717444">"Pošlji"</string> + <string name="label_pause_key" msgid="181098308428035340">"Premor"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Čakaj"</string> +</resources> diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml index dde01dd68..76e169b3e 100644 --- a/java/res/values-sl/strings.xml +++ b/java/res/values-sl/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dinamični plavajoči predogled"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Prikaz predlagane besede med vnosom s prstom"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: shranjeno"</string> - <string name="label_go_key" msgid="1635148082137219148">"Pojdi"</string> - <string name="label_next_key" msgid="362972844525672568">"Naprej"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Nazaj"</string> - <string name="label_done_key" msgid="2441578748772529288">"Dokončano"</string> - <string name="label_send_key" msgid="2815056534433717444">"Pošlji"</string> - <string name="label_pause_key" msgid="181098308428035340">"Premor"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Čakaj"</string> <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-action-keys.xml b/java/res/values-sr/strings-action-keys.xml new file mode 100644 index 000000000..b1f0910bd --- /dev/null +++ b/java/res/values-sr/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml index e7f6904c1..16de76074 100644 --- a/java/res/values-sr/strings.xml +++ b/java/res/values-sr/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-sv/strings-action-keys.xml new file mode 100644 index 000000000..4e59fa501 --- /dev/null +++ b/java/res/values-sv/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Kör"</string> + <string name="label_next_key" msgid="362972844525672568">"Nästa"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Föreg"</string> + <string name="label_done_key" msgid="2441578748772529288">"Färdig"</string> + <string name="label_send_key" msgid="2815056534433717444">"Skicka"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Vänta"</string> +</resources> diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index 0fcca4837..32b8dbe22 100644 --- a/java/res/values-sv/strings.xml +++ b/java/res/values-sv/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Visa ordförslag vid svepskrivning"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Ordförslaget visas i rörelsen medan du skriver"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: sparat"</string> - <string name="label_go_key" msgid="1635148082137219148">"Kör"</string> - <string name="label_next_key" msgid="362972844525672568">"Nästa"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Föreg"</string> - <string name="label_done_key" msgid="2441578748772529288">"Färdig"</string> - <string name="label_send_key" msgid="2815056534433717444">"Skicka"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pausa"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Vänta"</string> <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-action-keys.xml b/java/res/values-sw/strings-action-keys.xml new file mode 100644 index 000000000..55442534d --- /dev/null +++ b/java/res/values-sw/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Nenda"</string> + <string name="label_next_key" msgid="362972844525672568">"Inayofuata"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Iliyotangulia"</string> + <string name="label_done_key" msgid="2441578748772529288">"Kwisha"</string> + <string name="label_send_key" msgid="2815056534433717444">"Tuma"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pumzisha"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Subiri"</string> +</resources> diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml index fbf868f24..f32fb7434 100644 --- a/java/res/values-sw/strings.xml +++ b/java/res/values-sw/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Kihakiki kinachobadilika cha kuelea"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Onyesha neno lililopendekezwa unapoonyesha ishara"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Imehifadhiwa"</string> - <string name="label_go_key" msgid="1635148082137219148">"Nenda"</string> - <string name="label_next_key" msgid="362972844525672568">"Inayofuata"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Iliyotangulia"</string> - <string name="label_done_key" msgid="2441578748772529288">"Kwisha"</string> - <string name="label_send_key" msgid="2815056534433717444">"Tuma"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pumzisha"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Subiri"</string> <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-sw540dp-land/dimens.xml b/java/res/values-sw540dp-land/dimens.xml index d79e8ca35..002493798 100644 --- a/java/res/values-sw540dp-land/dimens.xml +++ b/java/res/values-sw540dp-land/dimens.xml @@ -29,10 +29,10 @@ <fraction name="key_bottom_gap_gb">5.200%p</fraction> <fraction name="key_horizontal_gap_gb">1.447%p</fraction> - <fraction name="keyboard_top_padding_ics">2.727%p</fraction> - <fraction name="keyboard_bottom_padding_ics">0.0%p</fraction> - <fraction name="key_bottom_gap_ics">4.5%p</fraction> - <fraction name="key_horizontal_gap_ics">0.9%p</fraction> + <fraction name="keyboard_top_padding_holo">2.727%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">4.5%p</fraction> + <fraction name="key_horizontal_gap_holo">0.9%p</fraction> <dimen name="popup_key_height">81.9dp</dimen> diff --git a/java/res/values-sw540dp/config.xml b/java/res/values-sw540dp/config.xml index 027780ce3..ac992ea23 100644 --- a/java/res/values-sw540dp/config.xml +++ b/java/res/values-sw540dp/config.xml @@ -20,7 +20,6 @@ <resources> <bool name="config_enable_show_option_of_key_preview_popup">false</bool> - <bool name="config_enable_bigram_suggestions_option">false</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_key_preview_popup">false</bool> <bool name="config_default_sound_enabled">true</bool> diff --git a/java/res/values-sw540dp/dimens.xml b/java/res/values-sw540dp/dimens.xml index b2f4ae043..801b7acb5 100644 --- a/java/res/values-sw540dp/dimens.xml +++ b/java/res/values-sw540dp/dimens.xml @@ -32,10 +32,10 @@ <fraction name="key_bottom_gap_gb">4.625%p</fraction> <fraction name="key_horizontal_gap_gb">2.113%p</fraction> - <fraction name="keyboard_top_padding_ics">2.335%p</fraction> - <fraction name="keyboard_bottom_padding_ics">4.0%p</fraction> - <fraction name="key_bottom_gap_ics">4.5%p</fraction> - <fraction name="key_horizontal_gap_ics">1.565%p</fraction> + <fraction name="keyboard_top_padding_holo">2.335%p</fraction> + <fraction name="keyboard_bottom_padding_holo">4.0%p</fraction> + <fraction name="key_bottom_gap_holo">4.5%p</fraction> + <fraction name="key_horizontal_gap_holo">1.565%p</fraction> <dimen name="more_keys_keyboard_key_horizontal_padding">6dp</dimen> <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> @@ -66,9 +66,9 @@ <fraction name="key_letter_ratio_5row">52%</fraction> <fraction name="key_uppercase_letter_ratio_5row">27%</fraction> - <dimen name="key_preview_offset_ics">8.0dp</dimen> + <dimen name="key_preview_offset_holo">8.0dp</dimen> <!-- popup_key_height x -0.5 --> - <dimen name="more_keys_keyboard_vertical_correction_ics">-31.5dp</dimen> + <dimen name="more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen> <dimen name="suggestions_strip_height">44dp</dimen> <dimen name="more_suggestions_row_height">44dp</dimen> diff --git a/java/res/values-sw540dp/touch-position-correction.xml b/java/res/values-sw540dp/touch-position-correction.xml index df07c1295..932b8fc72 100644 --- a/java/res/values-sw540dp/touch-position-correction.xml +++ b/java/res/values-sw540dp/touch-position-correction.xml @@ -48,7 +48,7 @@ </string-array> <string-array - name="touch_position_correction_data_ics" + name="touch_position_correction_data_holo" translatable="false" > <!-- The default touch position data (See com.android.inputmethod.keyboard.ProximityInfo) diff --git a/java/res/values-sw768dp-land/dimens.xml b/java/res/values-sw768dp-land/dimens.xml index ce315b0fc..653f5e7d5 100644 --- a/java/res/values-sw768dp-land/dimens.xml +++ b/java/res/values-sw768dp-land/dimens.xml @@ -29,10 +29,10 @@ <fraction name="key_bottom_gap_gb">3.896%p</fraction> <fraction name="key_horizontal_gap_gb">1.195%p</fraction> - <fraction name="keyboard_top_padding_ics">1.896%p</fraction> - <fraction name="keyboard_bottom_padding_ics">0.0%p</fraction> - <fraction name="key_bottom_gap_ics">3.690%p</fraction> - <fraction name="key_horizontal_gap_ics">1.030%p</fraction> + <fraction name="keyboard_top_padding_holo">1.896%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">3.690%p</fraction> + <fraction name="key_horizontal_gap_holo">1.030%p</fraction> <dimen name="popup_key_height">81.9dp</dimen> @@ -53,7 +53,7 @@ <fraction name="key_letter_ratio_5row">53%</fraction> <fraction name="key_uppercase_letter_ratio_5row">30%</fraction> - <dimen name="key_preview_offset_ics">8.0dp</dimen> + <dimen name="key_preview_offset_holo">8.0dp</dimen> <dimen name="suggestions_strip_padding">252.0dp</dimen> <fraction name="min_more_suggestions_width">50%</fraction> diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml index e1c07d6f8..c5c6aa4bf 100644 --- a/java/res/values-sw768dp/config.xml +++ b/java/res/values-sw768dp/config.xml @@ -21,7 +21,6 @@ <resources> <bool name="config_enable_show_voice_key_option">false</bool> <bool name="config_enable_show_option_of_key_preview_popup">false</bool> - <bool name="config_enable_bigram_suggestions_option">false</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_key_preview_popup">false</bool> <bool name="config_default_sound_enabled">true</bool> diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml index c90da7fed..4671aa28b 100644 --- a/java/res/values-sw768dp/dimens.xml +++ b/java/res/values-sw768dp/dimens.xml @@ -30,10 +30,10 @@ <fraction name="key_bottom_gap_gb">4.687%p</fraction> <fraction name="key_horizontal_gap_gb">1.272%p</fraction> - <fraction name="keyboard_top_padding_ics">2.335%p</fraction> - <fraction name="keyboard_bottom_padding_ics">0.0%p</fraction> - <fraction name="key_bottom_gap_ics">3.312%p</fraction> - <fraction name="key_horizontal_gap_ics">1.066%p</fraction> + <fraction name="keyboard_top_padding_holo">2.335%p</fraction> + <fraction name="keyboard_bottom_padding_holo">0.0%p</fraction> + <fraction name="key_bottom_gap_holo">3.312%p</fraction> + <fraction name="key_horizontal_gap_holo">1.066%p</fraction> <dimen name="popup_key_height">63.0dp</dimen> @@ -66,9 +66,9 @@ <fraction name="key_letter_ratio_5row">51%</fraction> <fraction name="key_uppercase_letter_ratio_5row">33%</fraction> - <dimen name="key_preview_offset_ics">8.0dp</dimen> + <dimen name="key_preview_offset_holo">8.0dp</dimen> <!-- popup_key_height x -0.5 --> - <dimen name="more_keys_keyboard_vertical_correction_ics">-31.5dp</dimen> + <dimen name="more_keys_keyboard_vertical_correction_holo">-31.5dp</dimen> <dimen name="suggestions_strip_height">44dp</dimen> <dimen name="more_suggestions_row_height">44dp</dimen> diff --git a/java/res/values-th/strings-action-keys.xml b/java/res/values-th/strings-action-keys.xml new file mode 100644 index 000000000..3fd9b4d31 --- /dev/null +++ b/java/res/values-th/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml index f84b32c62..d18d5c157 100644 --- a/java/res/values-th/strings.xml +++ b/java/res/values-th/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-tl/strings-action-keys.xml new file mode 100644 index 000000000..289c5e38a --- /dev/null +++ b/java/res/values-tl/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Punta"</string> + <string name="label_next_key" msgid="362972844525672568">"Susunod"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Nkrn"</string> + <string name="label_done_key" msgid="2441578748772529288">"Tapos na"</string> + <string name="label_send_key" msgid="2815056534433717444">"Ipadala"</string> + <string name="label_pause_key" msgid="181098308428035340">"Pause"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Intay"</string> +</resources> diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml index af1c68e01..e6a0aa705 100644 --- a/java/res/values-tl/strings.xml +++ b/java/res/values-tl/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamic na floating preview"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Tingnan ang iminungkahing salita habang gumagalaw"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Na-save"</string> - <string name="label_go_key" msgid="1635148082137219148">"Punta"</string> - <string name="label_next_key" msgid="362972844525672568">"Susunod"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Nkrn"</string> - <string name="label_done_key" msgid="2441578748772529288">"Tapos na"</string> - <string name="label_send_key" msgid="2815056534433717444">"Ipadala"</string> - <string name="label_pause_key" msgid="181098308428035340">"Pause"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Intay"</string> <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-action-keys.xml b/java/res/values-tr/strings-action-keys.xml new file mode 100644 index 000000000..b1b389aa8 --- /dev/null +++ b/java/res/values-tr/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Git"</string> + <string name="label_next_key" msgid="362972844525672568">"İleri"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Önceki"</string> + <string name="label_done_key" msgid="2441578748772529288">"Bitti"</string> + <string name="label_send_key" msgid="2815056534433717444">"Gönder"</string> + <string name="label_pause_key" msgid="181098308428035340">"Durkl"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Bekle"</string> +</resources> diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml index 4c8e1a81d..e5d999688 100644 --- a/java/res/values-tr/strings.xml +++ b/java/res/values-tr/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dinamik kayan önizleme"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Hareket sırasında önerilen kelimeyi göster"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kaydedildi"</string> - <string name="label_go_key" msgid="1635148082137219148">"Git"</string> - <string name="label_next_key" msgid="362972844525672568">"İleri"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Önceki"</string> - <string name="label_done_key" msgid="2441578748772529288">"Bitti"</string> - <string name="label_send_key" msgid="2815056534433717444">"Gönder"</string> - <string name="label_pause_key" msgid="181098308428035340">"Durkl"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Bekle"</string> <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-action-keys.xml b/java/res/values-uk/strings-action-keys.xml new file mode 100644 index 000000000..97c30389e --- /dev/null +++ b/java/res/values-uk/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"OK"</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> +</resources> diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml index 287bcb397..dc34ef58f 100644 --- a/java/res/values-uk/strings.xml +++ b/java/res/values-uk/strings.xml @@ -74,20 +74,11 @@ <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">"OK"</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> - <!-- 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-action-keys.xml b/java/res/values-vi/strings-action-keys.xml new file mode 100644 index 000000000..4cd7a9fea --- /dev/null +++ b/java/res/values-vi/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Tìm"</string> + <string name="label_next_key" msgid="362972844525672568">"Tiếp theo"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Trước"</string> + <string name="label_done_key" msgid="2441578748772529288">"Xong"</string> + <string name="label_send_key" msgid="2815056534433717444">"Gửi"</string> + <string name="label_pause_key" msgid="181098308428035340">"Tạm dừng"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Đợi"</string> +</resources> diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml index 8764df5e0..5520a2e64 100644 --- a/java/res/values-vi/strings.xml +++ b/java/res/values-vi/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Xem trước nổi động"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Xem từ được đề xuất trong khi dùng cử chỉ"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Đã lưu"</string> - <string name="label_go_key" msgid="1635148082137219148">"Tìm"</string> - <string name="label_next_key" msgid="362972844525672568">"Tiếp theo"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Trước"</string> - <string name="label_done_key" msgid="2441578748772529288">"Xong"</string> - <string name="label_send_key" msgid="2815056534433717444">"Gửi"</string> - <string name="label_pause_key" msgid="181098308428035340">"Tạm dừng"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Đợi"</string> <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-action-keys.xml b/java/res/values-zh-rCN/strings-action-keys.xml new file mode 100644 index 000000000..af0472ee9 --- /dev/null +++ b/java/res/values-zh-rCN/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml index f7ceff44f..a5a326c29 100644 --- a/java/res/values-zh-rCN/strings.xml +++ b/java/res/values-zh-rCN/strings.xml @@ -74,20 +74,11 @@ <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> - <!-- 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-action-keys.xml b/java/res/values-zh-rHK/strings-action-keys.xml new file mode 100644 index 000000000..332519f0a --- /dev/null +++ b/java/res/values-zh-rHK/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> 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..ee833ce79 --- /dev/null +++ b/java/res/values-zh-rHK/strings.xml @@ -0,0 +1,239 @@ +<?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="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">"您的流動裝置所選取的語言現有字典可供使用。<br/>建議您<b>下載</b><xliff:g id="LANGUAGE">%1$s</xliff:g>字典,讓您輸入時更方便。<br/><br/>經由 3G 網絡下載需時一兩分鐘。如果您未使用<b>無限上網計劃</b>,可能須另外付費。<br/>如果您不確定自己使用哪種上網計劃,建議您在連接 Wi-Fi 網絡後才開始自動下載。<br/><br/>提示:您可以前往流動裝置的 [設定] <b></b>選單,透過其中的 [語言和輸入] <b></b>下載和移除字典。"</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-action-keys.xml b/java/res/values-zh-rTW/strings-action-keys.xml new file mode 100644 index 000000000..80045b08d --- /dev/null +++ b/java/res/values-zh-rTW/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <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> +</resources> diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml index b773ad21c..21b2bec7e 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,26 +68,17 @@ <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> - <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> - <!-- 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 +169,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-action-keys.xml b/java/res/values-zu/strings-action-keys.xml new file mode 100644 index 000000000..054b4946c --- /dev/null +++ b/java/res/values-zu/strings-action-keys.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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="label_go_key" msgid="1635148082137219148">"Iya"</string> + <string name="label_next_key" msgid="362972844525672568">"Okulandelayo"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Eledlule"</string> + <string name="label_done_key" msgid="2441578748772529288">"Kwenziwe"</string> + <string name="label_send_key" msgid="2815056534433717444">"Thumela"</string> + <string name="label_pause_key" msgid="181098308428035340">"Misa okwesikhashana"</string> + <string name="label_wait_key" msgid="6402152600878093134">"Linda"</string> +</resources> diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml index 8f722cce3..b8b753cde 100644 --- a/java/res/values-zu/strings.xml +++ b/java/res/values-zu/strings.xml @@ -74,20 +74,11 @@ <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Ukuhlola kuqala okuntantayo okunamandla"</string> <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Bona igama eliphakanyisiwe ngenkathi uthinta"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kulondoloziwe"</string> - <string name="label_go_key" msgid="1635148082137219148">"Iya"</string> - <string name="label_next_key" msgid="362972844525672568">"Okulandelayo"</string> - <string name="label_previous_key" msgid="1211868118071386787">"Eledlule"</string> - <string name="label_done_key" msgid="2441578748772529288">"Kwenziwe"</string> - <string name="label_send_key" msgid="2815056534433717444">"Thumela"</string> - <string name="label_pause_key" msgid="181098308428035340">"Misa okwesikhashana"</string> - <string name="label_wait_key" msgid="6402152600878093134">"Linda"</string> <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/values/attrs.xml b/java/res/values/attrs.xml index 31945d020..a7425f1e7 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -276,6 +276,8 @@ <attr name="keyLabel" format="string" /> <!-- The hint label to display on the key in conjunction with the label. --> <attr name="keyHintLabel" format="string" /> + <!-- The vertical adjustment of key hint label in proportion to its height. --> + <attr name="keyHintLabelVerticalAdjustment" format="fraction" /> <!-- The key label flags. --> <attr name="keyLabelFlags" format="integer"> <!-- This should be aligned with Key.LABEL_FLAGS__* --> @@ -295,14 +297,16 @@ <flag name="withIconLeft" value="0x1000" /> <flag name="withIconRight" value="0x2000" /> <flag name="autoXScale" value="0x4000" /> + <!-- The autoScale value implies autoXScale bit on to optimize scaling code path. --> + <flag name="autoScale" value="0xc000" /> <!-- If true, character case of code, altCode, moreKeys, keyOutputText, keyLabel, or keyHintLabel will never be subject to change. --> - <flag name="preserveCase" value="0x8000" /> + <flag name="preserveCase" value="0x10000" /> <!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and keyTextInactivatedColor for the primary key top label. --> - <flag name="shiftedLetterActivated" value="0x10000" /> + <flag name="shiftedLetterActivated" value="0x20000" /> <!-- If true, use EditorInfo.actionLabel for the key label. --> - <flag name="fromCustomActionLabel" value="0x20000" /> + <flag name="fromCustomActionLabel" value="0x40000" /> <!-- If true, disable keyHintLabel. --> <flag name="disableKeyHintLabel" value="0x40000000" /> <!-- If true, disable additionalMoreKeys. --> diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml index 94fadb964..93f25a7f6 100644 --- a/java/res/values/colors.xml +++ b/java/res/values/colors.xml @@ -39,20 +39,20 @@ <color name="typed_word_color_ics">#D833B5E5</color> <color name="suggested_word_color_ics">#B233B5E5</color> <color name="highlight_translucent_color_ics">#9933B5E5</color> - <color name="key_text_shadow_color_ics">@android:color/transparent</color> - <color name="key_text_inactivated_color_ics">#66E0E4E5</color> - <color name="key_hint_letter_color_ics">#80000000</color> - <color name="key_hint_label_color_ics">#A0FFFFFF</color> - <color name="key_shifted_letter_hint_inactivated_color_ics">#66E0E4E5</color> - <color name="key_shifted_letter_hint_activated_color_ics">@android:color/white</color> - <color name="spacebar_text_color_ics">#FFC0C0C0</color> - <color name="spacebar_text_shadow_color_ics">#80000000</color> - <color name="gesture_floating_preview_color_ics">#C0000000</color> + <color name="key_text_shadow_color_holo">@android:color/transparent</color> + <color name="key_text_inactivated_color_holo">#66E0E4E5</color> + <color name="key_hint_letter_color_holo">#80000000</color> + <color name="key_hint_label_color_holo">#A0FFFFFF</color> + <color name="key_shifted_letter_hint_inactivated_color_holo">#66E0E4E5</color> + <color name="key_shifted_letter_hint_activated_color_holo">@android:color/white</color> + <color name="spacebar_text_color_holo">#FFC0C0C0</color> + <color name="spacebar_text_shadow_color_holo">#80000000</color> + <color name="gesture_floating_preview_color_holo">#C0000000</color> <!-- Color resources for KLP theme. Base color = F0F0F0 --> - <color name="highlight_color_holo">#FFF0F0F0</color> - <color name="typed_word_color_holo">#D8F0F0F0</color> - <color name="suggested_word_color_holo">#B2F0F0F0</color> - <color name="highlight_translucent_color_holo">#99E0E0E0</color> + <color name="highlight_color_klp">#FFF0F0F0</color> + <color name="typed_word_color_klp">#D8F0F0F0</color> + <color name="suggested_word_color_klp">#B2F0F0F0</color> + <color name="highlight_translucent_color_klp">#99E0E0E0</color> <!-- Color resources for setup wizard and tutorial --> <color name="setup_background">#FFEBEBEB</color> <color name="setup_text_dark">#FF707070</color> @@ -66,6 +66,6 @@ <color name="emoji_key_background_color">#00000000</color> <color name="emoji_key_pressed_background_color">#30FFFFFF</color> - <color name="key_text_color_normal_ics">@android:color/white</color> - <color name="key_text_color_functional_ics">@android:color/white</color> + <color name="key_text_color_normal_holo">@android:color/white</color> + <color name="key_text_color_functional_holo">@android:color/white</color> </resources> diff --git a/java/res/values/config.xml b/java/res/values/config.xml index 66b9b7082..61779d4b5 100644 --- a/java/res/values/config.xml +++ b/java/res/values/config.xml @@ -41,8 +41,8 @@ <integer name="config_keyboard_grid_width">32</integer> <integer name="config_keyboard_grid_height">16</integer> <integer name="config_double_space_period_timeout">1100</integer> - <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> - <string name="config_default_keyboard_theme_index" translatable="false">0</string> + <!-- This configuration is an index of {@link KeyboardSwitcher#KEYBOARD_THEMES[]}. --> + <string name="config_default_keyboard_theme_index" translatable="false">2</string> <integer name="config_max_more_keys_column">5</integer> <!-- diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml index 18cb262e2..4588b10eb 100644 --- a/java/res/values/dimens.xml +++ b/java/res/values/dimens.xml @@ -37,10 +37,10 @@ <fraction name="key_bottom_gap_gb">6.495%p</fraction> <fraction name="key_horizontal_gap_gb">1.971%p</fraction> - <fraction name="keyboard_top_padding_ics">2.335%p</fraction> - <fraction name="keyboard_bottom_padding_ics">4.669%p</fraction> - <fraction name="key_bottom_gap_ics">6.127%p</fraction> - <fraction name="key_horizontal_gap_ics">1.739%p</fraction> + <fraction name="keyboard_top_padding_holo">2.335%p</fraction> + <fraction name="keyboard_bottom_padding_holo">4.669%p</fraction> + <fraction name="key_bottom_gap_holo">6.127%p</fraction> + <fraction name="key_horizontal_gap_holo">1.739%p</fraction> <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> <!-- popup_key_height x 1.2 --> @@ -71,9 +71,9 @@ <fraction name="key_letter_ratio_5row">64%</fraction> <fraction name="key_uppercase_letter_ratio_5row">41%</fraction> - <dimen name="key_preview_offset_ics">8.0dp</dimen> + <dimen name="key_preview_offset_holo">8.0dp</dimen> <!-- popup_key_height x -0.5 --> - <dimen name="more_keys_keyboard_vertical_correction_ics">-26.4dp</dimen> + <dimen name="more_keys_keyboard_vertical_correction_holo">-26.4dp</dimen> <dimen name="suggestions_strip_height">40dp</dimen> <dimen name="more_suggestions_key_horizontal_padding">12dp</dimen> diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml index 4733aa257..af5ec061b 100644 --- a/java/res/values/donottranslate.xml +++ b/java/res/values/donottranslate.xml @@ -103,15 +103,30 @@ <!-- Keyboard theme names --> <string name="layout_gingerbread">Gingerbread</string> <string name="layout_ics">IceCreamSandwich</string> + <string name="layout_klp">KeyLimePie</string> <!-- For keyboard theme switcher dialog --> <string-array name="keyboard_layout_modes"> <item>@string/layout_ics</item> <item>@string/layout_gingerbread</item> + <item>@string/layout_klp</item> </string-array> + <!-- An element must be an index of {@link KeyboardSwitcher#KEYBOARD_THEMES[]}. --> <string-array name="keyboard_layout_modes_values"> <item>0</item> <item>1</item> + <item>2</item> + </string-array> + + <!-- For keyboard color scheme option dialog. --> + <string-array name="keyboard_color_schemes"> + <item>@string/keyboard_color_scheme_white</item> + <item>@string/keyboard_color_scheme_blue</item> + </string-array> + <!-- An element must be an index of {@link KeyboardSwitcher#KEYBOARD_THEMES[]}. --> + <string-array name="keyboard_color_schemes_values"> + <item>2</item> + <item>0</item> </string-array> <!-- Subtype locale display name exceptions. diff --git a/java/res/values/keyboard-icons-holo.xml b/java/res/values/keyboard-icons-holo.xml new file mode 100644 index 000000000..b49e1d10b --- /dev/null +++ b/java/res/values/keyboard-icons-holo.xml @@ -0,0 +1,45 @@ +<?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"> + <style name="KeyboardIcons.Holo"> + <!-- Keyboard icons --> + <!-- TODO: The following holo icon for phone (drawable-hdpi and drawable-xhdpi) are missing. + sym_keyboard_123_mic_holo + --> + <item name="iconShiftKey">@drawable/sym_keyboard_shift_holo_dark</item> + <item name="iconDeleteKey">@drawable/sym_keyboard_delete_holo_dark</item> + <item name="iconSettingsKey">@drawable/sym_keyboard_settings_holo_dark</item> + <item name="iconSpaceKey">@null</item> + <item name="iconEnterKey">@drawable/sym_keyboard_return_holo_dark</item> + <item name="iconSearchKey">@drawable/sym_keyboard_search_holo_dark</item> + <item name="iconTabKey">@drawable/sym_keyboard_tab_holo_dark</item> + <item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo_dark</item> + <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo_dark</item> + <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo_dark</item> + <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo_dark</item> + <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_holo_dark</item> + <item name="iconTabKeyPreview">@drawable/sym_keyboard_feedback_tab</item> + <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_dark</item> + <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo_dark</item> + <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo_dark</item> + <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_holo_dark</item> + </style> +</resources> diff --git a/java/res/values/keypress-vibration-durations.xml b/java/res/values/keypress-vibration-durations.xml index ee0ac003c..cde4e4447 100644 --- a/java/res/values/keypress-vibration-durations.xml +++ b/java/res/values/keypress-vibration-durations.xml @@ -55,6 +55,8 @@ <item>MODEL=HTL22:MANUFACTURER=HTC,15</item> <!-- Motorola Razor M --> <item>MODEL=XT907:MANUFACTURER=motorola,30</item> + <!-- Motorola DVX --> + <item>MODEL=XT1035:MANUFACTURER=motorola,18</item> <!-- Sony Xperia Z, Z Ultra --> <item>MODEL=C6603|C6806:MANUFACTURER=Sony,35</item> <!-- Default value for unknown device. The negative value means system default. --> diff --git a/java/res/values/strings-action-keys.xml b/java/res/values/strings-action-keys.xml new file mode 100644 index 000000000..7003784c6 --- /dev/null +++ b/java/res/values/strings-action-keys.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2013, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Label for soft enter key when it performs GO action. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7] --> + <string name="label_go_key">Go</string> + <!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7] --> + <string name="label_next_key">Next</string> + <!-- Label for soft enter key when it performs PREVIOUS action. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7] --> + <string name="label_previous_key">Prev</string> + <!-- Label for soft enter key when it performs DONE action. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7] --> + <string name="label_done_key">Done</string> + <!-- Label for soft enter key when it performs SEND action. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7] --> + <string name="label_send_key">Send</string> + <!-- Label for "Pause" key of phone number keyboard. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7] --> + <string name="label_pause_key">Pause</string> + <!-- Label for "Wait" key of phone number keyboard. Must be short to fit on key. 5 chars or less is preferable. [CHAR LIMIT=7]--> + <string name="label_wait_key">Wait</string> +</resources> diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index a779c6efa..11b3ea3af 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -151,21 +151,6 @@ <!-- Indicates that a word has been added to the dictionary --> <string name="added_word"><xliff:g id="word">%s</xliff:g> : Saved</string> - <!-- Label for soft enter key when it performs GO action. Must be short to fit on key! [CHAR LIMIT=5] --> - <string name="label_go_key">Go</string> - <!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key! [CHAR LIMIT=5] --> - <string name="label_next_key">Next</string> - <!-- Label for soft enter key when it performs PREVIOUS action. Must be short to fit on key! [CHAR LIMIT=5] --> - <string name="label_previous_key">Prev</string> - <!-- Label for soft enter key when it performs DONE action. Must be short to fit on key! [CHAR LIMIT=5] --> - <string name="label_done_key">Done</string> - <!-- Label for soft enter key when it performs SEND action. Must be short to fit on key! [CHAR LIMIT=5] --> - <string name="label_send_key">Send</string> - <!-- Label for "Pause" key of phone number keyboard. Must be short to fit on key! [CHAR LIMIT=5] --> - <string name="label_pause_key">Pause</string> - <!-- Label for "Wait" key of phone number keyboard. Must be short to fit on key! [CHAR LIMIT=5]--> - <string name="label_wait_key">Wait</string> - <!-- Spoken description to let the user know that when typing in a password, they can plug in a headset in to hear spoken descriptions of the keys they type. [CHAR LIMIT=NONE] --> <string name="spoken_use_headphones">Plug in a headset to hear password keys spoken aloud.</string> @@ -467,6 +452,13 @@ mobile devices. [CHAR LIMIT=25] --> <!-- Description for Emoji keyboard subtype [CHAR LIMIT=25] --> <string name="subtype_emoji">Emoji</string> + <!-- Title of the preference settings for switching keyboard color scheme [CHAR LIMIT=35] --> + <string name="keyboard_color_scheme">Color scheme</string> + <!-- The keyboard color scheme name, White [CHAR LIMIT=16] --> + <string name="keyboard_color_scheme_white">White</string> + <!-- The keyboard color scheme name, Blue [CHAR LIMIT=16] --> + <string name="keyboard_color_scheme_blue">Blue</string> + <!-- Title of the preference settings for custom input styles (language and keyboard layout pairs) [CHAR LIMIT=35]--> <string name="custom_input_styles_title">Custom input styles</string> <!-- Title of the option menu to add a new style entry in the preference settings [CHAR LIMIT=16] --> diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml index 37607711d..298936d9c 100644 --- a/java/res/values/themes-common.xml +++ b/java/res/values/themes-common.xml @@ -30,7 +30,7 @@ <item name="maxMoreKeysColumn">@integer/config_max_more_keys_column</item> </style> <style name="KeyboardView"> - <item name="keyBackground">@drawable/btn_keyboard_key_ics</item> + <item name="keyBackground">@drawable/btn_keyboard_key_klp</item> <item name="keyLetterSize">@fraction/key_letter_ratio</item> <item name="keyLargeLetterRatio">@fraction/key_large_letter_ratio</item> <item name="keyLabelSize">@fraction/key_label_ratio</item> @@ -110,7 +110,7 @@ name="EmojiPalettesView" parent="KeyboardView" > - <item name="emojiTabLabelColor">@color/emoji_tab_label_color_ics</item> + <item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item> </style> <style name="MoreKeysKeyboard" /> <style diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml index a77e685c2..432ad5122 100644 --- a/java/res/values/themes-ics.xml +++ b/java/res/values/themes-ics.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2011, The Android Open Source Project +** 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. @@ -19,7 +19,7 @@ --> <resources xmlns:android="http://schemas.android.com/apk/res/android"> - <style name="KeyboardTheme.ICS" parent="KeyboardIcons.ICS"> + <style name="KeyboardTheme.ICS" parent="KeyboardIcons.Holo"> <item name="keyboardStyle">@style/Keyboard.ICS</item> <item name="keyboardViewStyle">@style/KeyboardView.ICS</item> <item name="mainKeyboardViewStyle">@style/MainKeyboardView.ICS</item> @@ -30,40 +30,17 @@ <item name="suggestionStripViewStyle">@style/SuggestionStripView.ICS</item> <item name="suggestionWordStyle">@style/SuggestionWord.ICS</item> </style> - <style name="KeyboardIcons.ICS"> - <!-- Keyboard icons --> - <!-- TODO: The following holo icon for phone (drawable-hdpi and drawable-xhdpi) are missing. - sym_keyboard_123_mic_holo - --> - <item name="iconShiftKey">@drawable/sym_keyboard_shift_holo_dark</item> - <item name="iconDeleteKey">@drawable/sym_keyboard_delete_holo_dark</item> - <item name="iconSettingsKey">@drawable/sym_keyboard_settings_holo_dark</item> - <item name="iconSpaceKey">@null</item> - <item name="iconEnterKey">@drawable/sym_keyboard_return_holo_dark</item> - <item name="iconSearchKey">@drawable/sym_keyboard_search_holo_dark</item> - <item name="iconTabKey">@drawable/sym_keyboard_tab_holo_dark</item> - <item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo_dark</item> - <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo_dark</item> - <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo_dark</item> - <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo_dark</item> - <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_holo_dark</item> - <item name="iconTabKeyPreview">@drawable/sym_keyboard_feedback_tab</item> - <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch_dark</item> - <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo_dark</item> - <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo_dark</item> - <item name="iconEmojiKey">@drawable/sym_keyboard_smiley_holo_dark</item> - </style> <style name="Keyboard.ICS" parent="Keyboard" > <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> - <item name="themeId">0</item> - <item name="keyboardTopPadding">@fraction/keyboard_top_padding_ics</item> - <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_ics</item> - <item name="horizontalGap">@fraction/key_horizontal_gap_ics</item> - <item name="verticalGap">@fraction/key_bottom_gap_ics</item> - <item name="touchPositionCorrectionData">@array/touch_position_correction_data_ics</item> + <item name="themeId">2</item> + <item name="keyboardTopPadding">@fraction/keyboard_top_padding_holo</item> + <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_holo</item> + <item name="horizontalGap">@fraction/key_horizontal_gap_holo</item> + <item name="verticalGap">@fraction/key_bottom_gap_holo</item> + <item name="touchPositionCorrectionData">@array/touch_position_correction_data_holo</item> </style> <style name="KeyboardView.ICS" @@ -72,14 +49,14 @@ <item name="android:background">@drawable/keyboard_background_holo</item> <item name="keyBackground">@drawable/btn_keyboard_key_ics</item> <item name="keyTypeface">bold</item> - <item name="keyTextColor">@color/key_text_color_ics</item> - <item name="keyTextInactivatedColor">@color/key_text_inactivated_color_ics</item> - <item name="keyHintLetterColor">@color/key_hint_letter_color_ics</item> - <item name="keyHintLabelColor">@color/key_hint_label_color_ics</item> - <item name="keyShiftedLetterHintInactivatedColor">@color/key_shifted_letter_hint_inactivated_color_ics</item> - <item name="keyShiftedLetterHintActivatedColor">@color/key_shifted_letter_hint_activated_color_ics</item> - <item name="keyPreviewTextColor">@color/key_text_color_ics</item> - <item name="keyTextShadowColor">@color/key_text_shadow_color_ics</item> + <item name="keyTextColor">@color/key_text_color_holo</item> + <item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item> + <item name="keyHintLetterColor">@color/key_hint_letter_color_holo</item> + <item name="keyHintLabelColor">@color/key_hint_label_color_holo</item> + <item name="keyShiftedLetterHintInactivatedColor">@color/key_shifted_letter_hint_inactivated_color_holo</item> + <item name="keyShiftedLetterHintActivatedColor">@color/key_shifted_letter_hint_activated_color_holo</item> + <item name="keyPreviewTextColor">@color/key_text_color_holo</item> + <item name="keyTextShadowColor">@color/key_text_shadow_color_holo</item> <item name="keyTextShadowRadius">0.0</item> </style> <style @@ -87,15 +64,15 @@ parent="KeyboardView.ICS" > <item name="keyPreviewLayout">@layout/key_preview_ics</item> - <item name="keyPreviewOffset">@dimen/key_preview_offset_ics</item> - <item name="gestureFloatingPreviewTextColor">@color/highlight_color_holo</item> - <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_ics</item> - <item name="gestureTrailColor">@color/highlight_color_holo</item> - <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_holo</item> + <item name="keyPreviewOffset">@dimen/key_preview_offset_holo</item> + <item name="gestureFloatingPreviewTextColor">@color/highlight_color_ics</item> + <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item> + <item name="gestureTrailColor">@color/highlight_color_ics</item> + <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_ics</item> <item name="autoCorrectionSpacebarLedEnabled">false</item> <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item> - <item name="spacebarTextColor">@color/spacebar_text_color_ics</item> - <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_ics</item> + <item name="spacebarTextColor">@color/spacebar_text_color_holo</item> + <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> </style> <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, for instance delete button, need themed {@link KeyboardView} attributes. --> @@ -104,7 +81,7 @@ parent="KeyboardView.ICS" > <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_ics</item> - <item name="emojiTabLabelColor">@color/emoji_tab_label_color_ics</item> + <item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item> </style> <style name="MoreKeysKeyboard.ICS" @@ -122,12 +99,12 @@ <item name="android:background">@null</item> <item name="keyBackground">@drawable/btn_keyboard_key_popup_ics</item> <item name="keyTypeface">normal</item> - <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_ics</item> + <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_holo</item> </style> <style name="MoreKeysKeyboardContainer.ICS" > - <item name="android:background">@drawable/keyboard_popup_panel_background_holo</item> + <item name="android:background">@drawable/keyboard_popup_panel_background_ics</item> </style> <style name="SuggestionStripView.ICS" @@ -135,10 +112,10 @@ > <item name="android:background">@drawable/keyboard_suggest_strip_holo</item> <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item> - <item name="colorValidTypedWord">@color/typed_word_color_holo</item> - <item name="colorTypedWord">@color/typed_word_color_holo</item> - <item name="colorAutoCorrect">@color/highlight_color_holo</item> - <item name="colorSuggested">@color/suggested_word_color_holo</item> + <item name="colorValidTypedWord">@color/typed_word_color_ics</item> + <item name="colorTypedWord">@color/typed_word_color_ics</item> + <item name="colorAutoCorrect">@color/highlight_color_ics</item> + <item name="colorSuggested">@color/suggested_word_color_ics</item> <item name="alphaObsoleted">70%</item> </style> <style name="SuggestionWord.ICS"> diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml new file mode 100644 index 000000000..a3730019d --- /dev/null +++ b/java/res/values/themes-klp.xml @@ -0,0 +1,124 @@ +<?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"> + <style name="KeyboardTheme.KLP" parent="KeyboardIcons.Holo"> + <item name="keyboardStyle">@style/Keyboard.KLP</item> + <item name="keyboardViewStyle">@style/KeyboardView.KLP</item> + <item name="mainKeyboardViewStyle">@style/MainKeyboardView.KLP</item> + <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.KLP</item> + <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.KLP</item> + <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.KLP</item> + <item name="moreKeysKeyboardContainerStyle">@style/MoreKeysKeyboardContainer.KLP</item> + <item name="suggestionStripViewStyle">@style/SuggestionStripView.KLP</item> + <item name="suggestionWordStyle">@style/SuggestionWord.KLP</item> + </style> + <style + name="Keyboard.KLP" + parent="Keyboard" + > + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> + <item name="themeId">0</item> + <item name="keyboardTopPadding">@fraction/keyboard_top_padding_holo</item> + <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_holo</item> + <item name="horizontalGap">@fraction/key_horizontal_gap_holo</item> + <item name="verticalGap">@fraction/key_bottom_gap_holo</item> + <item name="touchPositionCorrectionData">@array/touch_position_correction_data_holo</item> + </style> + <style + name="KeyboardView.KLP" + parent="KeyboardView" + > + <item name="android:background">@drawable/keyboard_background_holo</item> + <item name="keyBackground">@drawable/btn_keyboard_key_klp</item> + <item name="keyTypeface">bold</item> + <item name="keyTextColor">@color/key_text_color_holo</item> + <item name="keyTextInactivatedColor">@color/key_text_inactivated_color_holo</item> + <item name="keyHintLetterColor">@color/key_hint_letter_color_holo</item> + <item name="keyHintLabelColor">@color/key_hint_label_color_holo</item> + <item name="keyShiftedLetterHintInactivatedColor">@color/key_shifted_letter_hint_inactivated_color_holo</item> + <item name="keyShiftedLetterHintActivatedColor">@color/key_shifted_letter_hint_activated_color_holo</item> + <item name="keyPreviewTextColor">@color/key_text_color_holo</item> + <item name="keyTextShadowColor">@color/key_text_shadow_color_holo</item> + <item name="keyTextShadowRadius">0.0</item> + </style> + <style + name="MainKeyboardView.KLP" + parent="KeyboardView.KLP" + > + <item name="keyPreviewLayout">@layout/key_preview_klp</item> + <item name="keyPreviewOffset">@dimen/key_preview_offset_holo</item> + <item name="gestureFloatingPreviewTextColor">@color/highlight_color_klp</item> + <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item> + <item name="gestureTrailColor">@color/highlight_color_klp</item> + <item name="slidingKeyInputPreviewColor">@color/highlight_translucent_color_klp</item> + <item name="autoCorrectionSpacebarLedEnabled">false</item> + <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item> + <item name="spacebarTextColor">@color/spacebar_text_color_holo</item> + <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> + </style> + <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, + for instance delete button, need themed {@link KeyboardView} attributes. --> + <style + name="EmojiPalettesView.KLP" + parent="KeyboardView.KLP" + > + <item name="keyBackgroundEmojiFunctional">@drawable/btn_keyboard_key_functional_klp</item> + <item name="emojiTabLabelColor">@color/emoji_tab_label_color_holo</item> + </style> + <style + name="MoreKeysKeyboard.KLP" + parent="Keyboard.KLP" + > + <item name="keyboardTopPadding">0%p</item> + <item name="keyboardBottomPadding">0%p</item> + <item name="horizontalGap">0%p</item> + <item name="touchPositionCorrectionData">@null</item> + </style> + <style + name="MoreKeysKeyboardView.KLP" + parent="KeyboardView.KLP" + > + <item name="android:background">@null</item> + <item name="keyBackground">@drawable/btn_keyboard_key_popup_klp</item> + <item name="keyTypeface">normal</item> + <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_holo</item> + </style> + <style + name="MoreKeysKeyboardContainer.KLP" + > + <item name="android:background">@drawable/keyboard_popup_panel_background_klp</item> + </style> + <style + name="SuggestionStripView.KLP" + parent="SuggestionStripView" + > + <item name="android:background">@drawable/keyboard_suggest_strip_holo</item> + <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item> + <item name="colorValidTypedWord">@color/typed_word_color_klp</item> + <item name="colorTypedWord">@color/typed_word_color_klp</item> + <item name="colorAutoCorrect">@color/highlight_color_klp</item> + <item name="colorSuggested">@color/suggested_word_color_klp</item> + <item name="alphaObsoleted">70%</item> + </style> + <style name="SuggestionWord.KLP"> + <item name="android:background">@drawable/btn_suggestion_klp</item> + </style> +</resources> diff --git a/java/res/values/touch-position-correction.xml b/java/res/values/touch-position-correction.xml index 9df517b32..becec0e0a 100644 --- a/java/res/values/touch-position-correction.xml +++ b/java/res/values/touch-position-correction.xml @@ -57,7 +57,7 @@ </string-array> <string-array - name="touch_position_correction_data_ics" + name="touch_position_correction_data_holo" translatable="false" > <!-- First row --> 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/key_f1.xml b/java/res/xml/key_f1.xml index 455f9ef59..72e38cb1a 100644 --- a/java/res/xml/key_f1.xml +++ b/java/res/xml/key_f1.xml @@ -47,7 +47,7 @@ <Key latin:keyLabel="!text/keylabel_for_comma" latin:keyLabelFlags="hasPopupHint" - latin:additionalMoreKeys="!text/more_keys_for_comma" + latin:additionalMoreKeys="!text/more_keys_for_comma,!text/shortcut_as_more_key" latin:keyStyle="f1MoreKeysStyle" /> </default> </switch> diff --git a/java/res/xml/key_nepali_traditional_period.xml b/java/res/xml/key_nepali_traditional_period.xml index 0f575c50b..1c389b009 100644 --- a/java/res/xml/key_nepali_traditional_period.xml +++ b/java/res/xml/key_nepali_traditional_period.xml @@ -39,10 +39,11 @@ set of Key definitions are needed based on the API version. --> <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_virama" /> + <!-- U+002E: "." FULL STOP --> <Key latin:keyStyle="baseKeyDevanagariSignVirama" latin:keyLabelFlags="hasPopupHint" - latin:moreKeys="!fixedColumnOrder!4,.,!text/more_keys_for_punctuation" + latin:moreKeys="!fixedColumnOrder!9,.,!text/more_keys_for_punctuation" latin:backgroundType="functional" /> </default> </switch> 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..26ceb8967 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 @@ -88,19 +90,22 @@ (zz: Emoji/emoji) --> <!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. --> +<!-- TODO: Remove "AsciiCapable" from the extra values when we can stop supporting JB-MR1 --> <!-- Note: SupportTouchPositionCorrection extra value is obsolete and maintained for backward compatibility. --> <!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default subtype.--> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.android.inputmethod.latin.settings.SettingsActivity" - android:isDefault="@bool/im_is_default"> + android:isDefault="@bool/im_is_default" + android:supportsSwitchingToNextInputMethod="true"> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_en_US" android:subtypeId="0xc9194f98" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_en_GB" @@ -108,6 +113,7 @@ android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -115,6 +121,7 @@ android:imeSubtypeLocale="af" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -122,6 +129,7 @@ android:imeSubtypeLocale="ar" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="false" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -130,6 +138,7 @@ android:imeSubtypeLocale="az" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -138,6 +147,7 @@ android:imeSubtypeLocale="be" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -145,6 +155,7 @@ android:imeSubtypeLocale="bg" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_bulgarian_bds" @@ -152,6 +163,7 @@ android:imeSubtypeLocale="bg" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=bulgarian_bds,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -159,6 +171,7 @@ android:imeSubtypeLocale="ca" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -166,6 +179,7 @@ android:imeSubtypeLocale="cs" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -173,6 +187,7 @@ android:imeSubtypeLocale="da" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -180,6 +195,15 @@ android:imeSubtypeLocale="de" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" + /> + <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" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -187,6 +211,7 @@ android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=greek,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -194,6 +219,7 @@ android:imeSubtypeLocale="eo" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -201,6 +227,7 @@ android:imeSubtypeLocale="es" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_es_US" @@ -208,6 +235,7 @@ android:imeSubtypeLocale="es_US" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -216,6 +244,7 @@ android:imeSubtypeLocale="es_419" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -224,6 +253,7 @@ android:imeSubtypeLocale="et_EE" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=nordic,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -231,6 +261,7 @@ android:imeSubtypeLocale="fa" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=farsi,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -238,6 +269,7 @@ android:imeSubtypeLocale="fi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -245,6 +277,7 @@ android:imeSubtypeLocale="fr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -252,6 +285,15 @@ android:imeSubtypeLocale="fr_CA" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" + /> + <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" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -259,6 +301,7 @@ android:imeSubtypeLocale="hi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=hindi,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -266,6 +309,7 @@ android:imeSubtypeLocale="hr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -273,6 +317,7 @@ android:imeSubtypeLocale="hu" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -280,6 +325,7 @@ android:imeSubtypeLocale="hy_AM" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=armenian_phonetic,EmojiCapable" + android:isAsciiCapable="false" /> <!-- Java uses the deprecated "in" code instead of the standard "id" code for Indonesian. --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -288,6 +334,7 @@ android:imeSubtypeLocale="in" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -295,6 +342,7 @@ android:imeSubtypeLocale="is" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -302,6 +350,7 @@ android:imeSubtypeLocale="it" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -310,6 +359,7 @@ android:imeSubtypeLocale="iw" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -317,6 +367,7 @@ android:imeSubtypeLocale="ka_GE" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=georgian,EmojiCapable" + android:isAsciiCapable="false" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -325,6 +376,7 @@ android:imeSubtypeLocale="kk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" + android:isAsciiCapable="false" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -333,6 +385,7 @@ android:imeSubtypeLocale="km_KH" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=khmer,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -340,6 +393,7 @@ android:imeSubtypeLocale="ky" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -347,6 +401,7 @@ android:imeSubtypeLocale="lo_LA" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=lao,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -354,6 +409,7 @@ android:imeSubtypeLocale="lt" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -361,6 +417,7 @@ android:imeSubtypeLocale="lv" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -368,6 +425,7 @@ android:imeSubtypeLocale="mk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=south_slavic,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -375,6 +433,7 @@ android:imeSubtypeLocale="mn_MN" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=mongolian,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -382,6 +441,7 @@ android:imeSubtypeLocale="ms_MY" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -389,6 +449,7 @@ android:imeSubtypeLocale="nb" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <!-- <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -397,6 +458,7 @@ android:imeSubtypeLocale="ne" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=nepali_romanized,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_nepali_traditional" @@ -404,6 +466,7 @@ android:imeSubtypeLocale="ne" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=nepali_traditional,EmojiCapable" + android:isAsciiCapable="false" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -412,6 +475,7 @@ android:imeSubtypeLocale="nl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -419,6 +483,7 @@ android:imeSubtypeLocale="nl_BE" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=azerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -426,6 +491,7 @@ android:imeSubtypeLocale="pl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -433,6 +499,7 @@ android:imeSubtypeLocale="pt_BR" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -440,6 +507,7 @@ android:imeSubtypeLocale="pt_PT" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -447,6 +515,7 @@ android:imeSubtypeLocale="ro" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -454,6 +523,7 @@ android:imeSubtypeLocale="ru" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -461,6 +531,7 @@ android:imeSubtypeLocale="sk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -468,6 +539,7 @@ android:imeSubtypeLocale="sl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -475,6 +547,7 @@ android:imeSubtypeLocale="sr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="false" /> <!-- TODO: Uncomment once we can handle IETF language tag with script name specified. <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -483,6 +556,7 @@ android:imeSubtypeLocale="sr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_serbian_latin" @@ -490,6 +564,7 @@ android:imeSubtypeLocale="sr-Latn" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> --> <subtype android:icon="@drawable/ic_ime_switcher_dark" @@ -498,6 +573,7 @@ android:imeSubtypeLocale="sv" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -505,6 +581,7 @@ android:imeSubtypeLocale="sw" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -512,6 +589,7 @@ android:imeSubtypeLocale="th" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=thai,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -519,6 +597,7 @@ android:imeSubtypeLocale="tl" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -526,6 +605,7 @@ android:imeSubtypeLocale="tr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -533,6 +613,7 @@ android:imeSubtypeLocale="uk" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable" + android:isAsciiCapable="false" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -540,6 +621,7 @@ android:imeSubtypeLocale="vi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_generic" @@ -547,6 +629,7 @@ android:imeSubtypeLocale="zu" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <subtype android:icon="@drawable/ic_ime_switcher_dark" android:label="@string/subtype_no_language_qwerty" @@ -554,6 +637,7 @@ android:imeSubtypeLocale="zz" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable,EmojiCapable" + android:isAsciiCapable="true" /> <!-- Emoji subtype has to be an addtional subtype added at boot time because ICS doesn't support Emoji. --> @@ -564,6 +648,7 @@ android:imeSubtypeLocale="zz" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=emoji,EmojiCapable" + android:isAsciiCapable="false" /> --> </input-method> diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index 6c36b0e89..d2b447545 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -158,6 +158,14 @@ android:summary="@string/sliding_key_input_preview_summary" android:persistent="true" android:defaultValue="true" /> + <ListPreference + android:key="pref_keyboard_layout_20110916" + android:title="@string/keyboard_color_scheme" + android:summary="%s" + android:persistent="true" + android:entryValues="@array/keyboard_color_schemes_values" + android:entries="@array/keyboard_color_schemes" + android:defaultValue="@string/config_default_keyboard_theme_index" /> <PreferenceScreen android:fragment="com.android.inputmethod.latin.settings.AdditionalSubtypeSettings" android:key="custom_input_styles" diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml index 5d89b9cb2..8d9508e38 100644 --- a/java/res/xml/prefs_for_debug.xml +++ b/java/res/xml/prefs_for_debug.xml @@ -28,6 +28,7 @@ <ListPreference android:key="pref_keyboard_layout_20110916" android:title="@string/keyboard_layout" + android:summary="%s" android:persistent="true" android:entryValues="@array/keyboard_layout_modes_values" android:entries="@array/keyboard_layout_modes" diff --git a/java/res/xml/row_dvorak4.xml b/java/res/xml/row_dvorak4.xml index 02a95acea..b78872fe4 100644 --- a/java/res/xml/row_dvorak4.xml +++ b/java/res/xml/row_dvorak4.xml @@ -27,42 +27,11 @@ <Key latin:keyStyle="toSymbolKeyStyle" latin:keyWidth="15%p" /> - <switch> - <case - latin:hasShortcutKey="true" - latin:keyboardLayoutSetElement="alphabet" - > - <Key - latin:keyLabel="q" - latin:backgroundType="normal" - latin:additionalMoreKeys="!text/shortcut_as_more_key" - latin:keyStyle="f1MoreKeysStyle" /> - </case> - <case - latin:hasShortcutKey="true" - > - <Key - latin:keyLabel="Q" - latin:backgroundType="normal" - latin:additionalMoreKeys="!text/shortcut_as_more_key" - latin:keyStyle="f1MoreKeysStyle" /> - </case> - <!-- latin:hasShortcutKey="false" --> - <case - latin:keyboardLayoutSetElement="alphabet" - > - <Key - latin:keyLabel="q" - latin:backgroundType="normal" - latin:keyStyle="f1MoreKeysStyle" /> - </case> - <default> - <Key - latin:keyLabel="Q" - latin:backgroundType="normal" - latin:keyStyle="f1MoreKeysStyle" /> - </default> - </switch> + <Key + latin:keyLabel="q" + latin:backgroundType="normal" + latin:additionalMoreKeys="!text/shortcut_as_more_key" + latin:keyStyle="f1MoreKeysStyle" /> <include latin:keyXPos="25%p" latin:keyboardLayout="@xml/key_space_5kw" /> diff --git a/java/res/xml/rowkeys_khmer1.xml b/java/res/xml/rowkeys_khmer1.xml index 25da66400..05d1a864a 100644 --- a/java/res/xml/rowkeys_khmer1.xml +++ b/java/res/xml/rowkeys_khmer1.xml @@ -64,6 +64,7 @@ <Key latin:keyLabel="័" latin:keyHintLabel="៚" + latin:keyHintLabelVerticalAdjustment="-30%" latin:moreKeys="៚" latin:keyLabelFlags="fontNormal" /> <!-- U+17CF: "៏" KHMER SIGN AHSDA --> diff --git a/java/res/xml/rowkeys_khmer2.xml b/java/res/xml/rowkeys_khmer2.xml index cba2d3b90..801f23ff6 100644 --- a/java/res/xml/rowkeys_khmer2.xml +++ b/java/res/xml/rowkeys_khmer2.xml @@ -31,12 +31,13 @@ latin:keyLabel="ឈ" latin:keyHintLabel="ៜ" latin:moreKeys="ៜ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|autoScale" /> <!-- U+17BA: "ឺ" KHMER VOWEL SIGN YY U+17DD: "៝" KHMER SIGN ATTHACAN --> <Key latin:keyLabel="ឺ" latin:keyHintLabel="៝" + latin:keyHintLabelVerticalAdjustment="40%" latin:moreKeys="៝" latin:keyLabelFlags="fontNormal" /> <!-- U+17C2: "ែ" KHMER VOWEL SIGN AE --> @@ -69,7 +70,7 @@ <!-- U+17C5: "ៅ" KHMER VOWEL SIGN AU --> <Key latin:keyLabel="ៅ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|autoScale" /> <!-- U+1797: "ភ" KHMER LETTER PHO --> <Key latin:keyLabel="ភ" @@ -77,7 +78,7 @@ <!-- U+17BF: "ឿ" KHMER VOWEL SIGN YA --> <Key latin:keyLabel="ឿ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|autoScale" /> <!-- U+17B0: "ឰ" KHMER INDEPENDENT VOWEL QAI --> <Key latin:keyLabel="ឰ" @@ -119,7 +120,7 @@ <!-- U+17C4: "ោ" KHMER VOWEL SIGN OO --> <Key latin:keyLabel="ោ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|autoScale" /> <!-- U+1795: "ផ" KHMER LETTER PHA --> <Key latin:keyLabel="ផ" @@ -127,7 +128,7 @@ <!-- U+17C0: "ៀ" KHMER VOWEL SIGN IE --> <Key latin:keyLabel="ៀ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|autoScale" /> <!-- U+17AA: "ឪ" KHMER INDEPENDENT VOWEL QUUV U+17A7: "ឧ" KHMER INDEPENDENT VOWEL QU U+17B1: "ឱ" KHMER INDEPENDENT VOWEL QOO TYPE ONE diff --git a/java/res/xml/rowkeys_khmer3.xml b/java/res/xml/rowkeys_khmer3.xml index ff6c9ca51..f35ba5c56 100644 --- a/java/res/xml/rowkeys_khmer3.xml +++ b/java/res/xml/rowkeys_khmer3.xml @@ -70,7 +70,7 @@ <!-- U+17C4/U+17C7: "ោះ" KHMER VOWEL SIGN OO/KHMER SIGN REAHMUK --> <Key latin:keyLabel="ោះ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|followKeyLetterRatio|autoScale" /> <!-- U+17C9: "៉" KHMER SIGN MUUSIKATOAN --> <Key latin:keyLabel="៉" diff --git a/java/res/xml/rowkeys_khmer4.xml b/java/res/xml/rowkeys_khmer4.xml index fe6c59125..598aed8d5 100644 --- a/java/res/xml/rowkeys_khmer4.xml +++ b/java/res/xml/rowkeys_khmer4.xml @@ -40,7 +40,7 @@ <!-- U+17C1/U+17C7: "េះ" KHMER VOWEL SIGN E/KHMER SIGN REAHMUK --> <Key latin:keyLabel="េះ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|followKeyLetterRatio|autoScale" /> <!-- U+1796: "ព" KHMER LETTER PO U+179E: "ឞ" KHMER LETTER SSO --> <Key @@ -51,7 +51,7 @@ <!-- U+178E: "ណ" KHMER LETTER NNO --> <Key latin:keyLabel="ណ" - latin:keyLabelFlags="fontNormal" /> + latin:keyLabelFlags="fontNormal|autoScale" /> <!-- U+17C6: "ំ" KHMER SIGN NIKAHIT --> <Key latin:keyLabel="ំ" 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/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/EmojiLayoutParams.java index ceb44e79f..967448c28 100644 --- a/java/src/com/android/inputmethod/keyboard/EmojiLayoutParams.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiLayoutParams.java @@ -40,13 +40,13 @@ public class EmojiLayoutParams { public EmojiLayoutParams(Resources res) { final int defaultKeyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res); final int defaultKeyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); - mKeyVerticalGap = (int) res.getFraction(R.fraction.key_bottom_gap_ics, + mKeyVerticalGap = (int) res.getFraction(R.fraction.key_bottom_gap_holo, (int) defaultKeyboardHeight, (int) defaultKeyboardHeight); - mBottomPadding = (int) res.getFraction(R.fraction.keyboard_bottom_padding_ics, + mBottomPadding = (int) res.getFraction(R.fraction.keyboard_bottom_padding_holo, (int) defaultKeyboardHeight, (int) defaultKeyboardHeight); - mTopPadding = (int) res.getFraction(R.fraction.keyboard_top_padding_ics, + mTopPadding = (int) res.getFraction(R.fraction.keyboard_top_padding_holo, (int) defaultKeyboardHeight, (int) defaultKeyboardHeight); - mKeyHorizontalGap = (int) (res.getFraction(R.fraction.key_horizontal_gap_ics, + mKeyHorizontalGap = (int) (res.getFraction(R.fraction.key_horizontal_gap_holo, defaultKeyboardWidth, defaultKeyboardWidth)); mEmojiCategoryPageIdViewHeight = (int) (res.getDimension(R.dimen.emoji_category_page_id_height)); diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java index f12373503..c375223cf 100644 --- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java @@ -44,8 +44,7 @@ import android.widget.TabHost.OnTabChangeListener; import android.widget.TextView; import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard; -import com.android.inputmethod.keyboard.internal.ScrollKeyboardView; -import com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier; +import com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; @@ -72,7 +71,7 @@ import java.util.concurrent.ConcurrentHashMap; */ public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener, ViewPager.OnPageChangeListener, View.OnClickListener, - ScrollKeyboardView.OnKeyClickListener { + EmojiPageKeyboardView.OnKeyClickListener { private static final String TAG = EmojiPalettesView.class.getSimpleName(); private static final boolean DEBUG_PAGER = false; private final int mKeyBackgroundId; @@ -628,16 +627,16 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } private static class EmojiPalettesAdapter extends PagerAdapter { - private final ScrollKeyboardView.OnKeyClickListener mListener; + private final EmojiPageKeyboardView.OnKeyClickListener mListener; private final DynamicGridKeyboard mRecentsKeyboard; - private final SparseArray<ScrollKeyboardView> mActiveKeyboardViews = + private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews = CollectionUtils.newSparseArray(); private final EmojiCategory mEmojiCategory; private int mActivePosition = 0; public EmojiPalettesAdapter(final EmojiCategory emojiCategory, final KeyboardLayoutSet layoutSet, - final ScrollKeyboardView.OnKeyClickListener listener) { + final EmojiPageKeyboardView.OnKeyClickListener listener) { mEmojiCategory = emojiCategory; mListener = listener; mRecentsKeyboard = mEmojiCategory.getKeyboard(CATEGORY_ID_RECENTS, 0); @@ -675,7 +674,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange if (mActivePosition == position) { return; } - final ScrollKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition); + final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition); if (oldKeyboardView != null) { oldKeyboardView.releaseCurrentKey(); oldKeyboardView.deallocateMemory(); @@ -688,7 +687,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange if (DEBUG_PAGER) { Log.d(TAG, "instantiate item: " + position); } - final ScrollKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position); + final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position); if (oldKeyboardView != null) { oldKeyboardView.deallocateMemory(); // This may be redundant but wanted to be safer.. @@ -697,18 +696,13 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange final Keyboard keyboard = mEmojiCategory.getKeyboardFromPagePosition(position); final LayoutInflater inflater = LayoutInflater.from(container.getContext()); - final View view = inflater.inflate( + final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate( R.layout.emoji_keyboard_page, container, false /* attachToRoot */); - final ScrollKeyboardView keyboardView = (ScrollKeyboardView)view.findViewById( - R.id.emoji_keyboard_page); keyboardView.setKeyboard(keyboard); keyboardView.setOnKeyClickListener(mListener); - final ScrollViewWithNotifier scrollView = (ScrollViewWithNotifier)view.findViewById( - R.id.emoji_keyboard_scroller); - keyboardView.setScrollView(scrollView); - container.addView(view); + container.addView(keyboardView); mActiveKeyboardViews.put(position, keyboardView); - return view; + return keyboardView; } @Override @@ -722,7 +716,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange if (DEBUG_PAGER) { Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName()); } - final ScrollKeyboardView keyboardView = mActiveKeyboardViews.get(position); + final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position); if (keyboardView != null) { keyboardView.deallocateMemory(); mActiveKeyboardViews.remove(position); diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index f7ec9509d..d3f628dcf 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -84,10 +84,16 @@ public class Key implements Comparable<Key> { private static final int LABEL_FLAGS_HAS_HINT_LABEL = 0x800; private static final int LABEL_FLAGS_WITH_ICON_LEFT = 0x1000; private static final int LABEL_FLAGS_WITH_ICON_RIGHT = 0x2000; + // The bit to calculate the ratio of key label width against key width. If autoXScale bit is on + // and autoYScale bit is off, the key label may be shrunk only for X-direction. + // If both autoXScale and autoYScale bits are on, the key label text size may be auto scaled. private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000; - private static final int LABEL_FLAGS_PRESERVE_CASE = 0x8000; - private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000; - private static final int LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL = 0x20000; + private static final int LABEL_FLAGS_AUTO_Y_SCALE = 0x8000; + private static final int LABEL_FLAGS_AUTO_SCALE = LABEL_FLAGS_AUTO_X_SCALE + | LABEL_FLAGS_AUTO_Y_SCALE; + private static final int LABEL_FLAGS_PRESERVE_CASE = 0x10000; + private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x20000; + private static final int LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL = 0x40000; private static final int LABEL_FLAGS_DISABLE_HINT_LABEL = 0x40000000; private static final int LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS = 0x80000000; @@ -702,10 +708,14 @@ public class Key implements Comparable<Key> { return (mLabelFlags & LABEL_FLAGS_WITH_ICON_RIGHT) != 0; } - public final boolean needsXScale() { + public final boolean needsAutoXScale() { return (mLabelFlags & LABEL_FLAGS_AUTO_X_SCALE) != 0; } + public final boolean needsAutoScale() { + return (mLabelFlags & LABEL_FLAGS_AUTO_SCALE) == LABEL_FLAGS_AUTO_SCALE; + } + public final boolean isShiftedLetterActivated() { return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index b7521b998..a6b293f2f 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -27,6 +27,7 @@ import android.view.View; import android.view.inputmethod.EditorInfo; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; +import com.android.inputmethod.compat.InputMethodServiceCompatUtils; import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException; import com.android.inputmethod.keyboard.internal.KeyboardState; import com.android.inputmethod.latin.InputView; @@ -57,9 +58,13 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { } } + private static final int INDEX_THEME_ICS = 0; + private static final int INDEX_THEME_GB = 1; + private static final int INDEX_THEME_KLP = 2; private static final KeyboardTheme[] KEYBOARD_THEMES = { - new KeyboardTheme(0, R.style.KeyboardTheme_ICS), - new KeyboardTheme(1, R.style.KeyboardTheme_GB), + new KeyboardTheme(INDEX_THEME_ICS, R.style.KeyboardTheme_ICS), + new KeyboardTheme(INDEX_THEME_GB, R.style.KeyboardTheme_GB), + new KeyboardTheme(INDEX_THEME_KLP, R.style.KeyboardTheme_KLP), }; private SubtypeSwitcher mSubtypeSwitcher; @@ -71,6 +76,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { private EmojiPalettesView mEmojiPalettesView; private LatinIME mLatinIME; private Resources mResources; + private boolean mIsHardwareAcceleratedDrawingEnabled; private KeyboardState mState; @@ -80,7 +86,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { * what user actually typed. */ private boolean mIsAutoCorrectionActive; - private KeyboardTheme mKeyboardTheme = KEYBOARD_THEMES[0]; + private KeyboardTheme mKeyboardTheme = KEYBOARD_THEMES[INDEX_THEME_KLP]; private Context mThemeContext; private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); @@ -104,7 +110,16 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mPrefs = prefs; mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mState = new KeyboardState(this); - setContextThemeWrapper(latinIme, getKeyboardTheme(latinIme, prefs)); + mIsHardwareAcceleratedDrawingEnabled = + InputMethodServiceCompatUtils.enableHardwareAcceleration(mLatinIME); + } + + public void updateKeyboardTheme() { + final boolean themeUpdated = updateKeyboardThemeAndContextThemeWrapper( + mLatinIME, getKeyboardTheme(mLatinIME, mPrefs)); + if (themeUpdated && mKeyboardView != null) { + mLatinIME.setInputView(onCreateInputView(mIsHardwareAcceleratedDrawingEnabled)); + } } private static KeyboardTheme getKeyboardTheme(final Context context, @@ -124,12 +139,15 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { return KEYBOARD_THEMES[Integer.valueOf(defaultIndex)]; } - private void setContextThemeWrapper(final Context context, final KeyboardTheme keyboardTheme) { + private boolean updateKeyboardThemeAndContextThemeWrapper(final Context context, + final KeyboardTheme keyboardTheme) { if (mThemeContext == null || mKeyboardTheme.mThemeId != keyboardTheme.mThemeId) { mKeyboardTheme = keyboardTheme; mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId); KeyboardLayoutSet.clearKeyboardCache(); + return true; } + return false; } public void loadKeyboard(final EditorInfo editorInfo, final SettingsValues settingsValues) { @@ -361,7 +379,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions { mKeyboardView.closing(); } - setContextThemeWrapper(mLatinIME, mKeyboardTheme); + updateKeyboardThemeAndContextThemeWrapper(mLatinIME, mKeyboardTheme); mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate( R.layout.input_view, null); mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 5578713a0..dcd90070e 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -113,9 +113,6 @@ public class KeyboardView extends View { private final Canvas mOffscreenCanvas = new Canvas(); private final Paint mPaint = new Paint(); private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics(); - private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' }; - private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' }; - public KeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); } @@ -370,10 +367,8 @@ public class KeyboardView extends View { if (label != null) { paint.setTypeface(key.selectTypeface(params)); paint.setTextSize(key.selectTextSize(params)); - final float labelCharHeight = TypefaceUtils.getCharHeight( - KEY_LABEL_REFERENCE_CHAR, paint); - final float labelCharWidth = TypefaceUtils.getCharWidth( - KEY_LABEL_REFERENCE_CHAR, paint); + final float labelCharHeight = TypefaceUtils.getReferenceCharHeight(paint); + final float labelCharWidth = TypefaceUtils.getReferenceCharWidth(paint); // Vertical label text alignment. final float baseline = centerY + labelCharHeight / 2.0f; @@ -391,12 +386,12 @@ public class KeyboardView extends View { positionX = centerX - labelCharWidth * 7.0f / 4.0f; paint.setTextAlign(Align.LEFT); } else if (key.hasLabelWithIconLeft() && icon != null) { - labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth() + labelWidth = TypefaceUtils.getStringWidth(label, paint) + icon.getIntrinsicWidth() + LABEL_ICON_MARGIN * keyWidth; positionX = centerX + labelWidth / 2.0f; paint.setTextAlign(Align.RIGHT); } else if (key.hasLabelWithIconRight() && icon != null) { - labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth() + labelWidth = TypefaceUtils.getStringWidth(label, paint) + icon.getIntrinsicWidth() + LABEL_ICON_MARGIN * keyWidth; positionX = centerX - labelWidth / 2.0f; paint.setTextAlign(Align.LEFT); @@ -404,9 +399,15 @@ public class KeyboardView extends View { positionX = centerX; paint.setTextAlign(Align.CENTER); } - if (key.needsXScale()) { - paint.setTextScaleX(Math.min(1.0f, - (keyWidth * MAX_LABEL_RATIO) / TypefaceUtils.getLabelWidth(label, paint))); + if (key.needsAutoXScale()) { + final float ratio = Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / + TypefaceUtils.getStringWidth(label, paint)); + if (key.needsAutoScale()) { + final float autoSize = paint.getTextSize() * ratio; + paint.setTextSize(autoSize); + } else { + paint.setTextScaleX(ratio); + } } paint.setColor(key.selectTextColor(params)); @@ -451,36 +452,35 @@ public class KeyboardView extends View { // TODO: Should add a way to specify type face for hint letters paint.setTypeface(Typeface.DEFAULT_BOLD); blendAlpha(paint, params.mAnimAlpha); + final float labelCharHeight = TypefaceUtils.getReferenceCharHeight(paint); + final float labelCharWidth = TypefaceUtils.getReferenceCharWidth(paint); + final KeyVisualAttributes visualAttr = key.getVisualAttributes(); + final float adjustmentY = (visualAttr == null) ? 0.0f + : visualAttr.mHintLabelVerticalAdjustment * labelCharHeight; final float hintX, hintY; if (key.hasHintLabel()) { // The hint label is placed just right of the key label. Used mainly on // "phone number" layout. // TODO: Generalize the following calculations. - hintX = positionX - + TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2.0f; - hintY = centerY - + TypefaceUtils.getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; + hintX = positionX + labelCharWidth * 2.0f; + hintY = centerY + labelCharHeight / 2.0f; paint.setTextAlign(Align.LEFT); } else if (key.hasShiftedLetterHint()) { // The hint label is placed at top-right corner of the key. Used mainly on tablet. - hintX = keyWidth - mKeyShiftedLetterHintPadding - - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; + hintX = keyWidth - mKeyShiftedLetterHintPadding - labelCharWidth / 2.0f; paint.getFontMetrics(mFontMetrics); hintY = -mFontMetrics.top; paint.setTextAlign(Align.CENTER); } else { // key.hasHintLetter() // The hint letter is placed at top-right corner of the key. Used mainly on phone. - final float keyNumericHintLabelReferenceCharWidth = - TypefaceUtils.getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint); - final float keyHintLabelStringWidth = - TypefaceUtils.getStringWidth(hintLabel, paint); + final float hintDigitWidth = TypefaceUtils.getReferenceDigitWidth(paint); + final float hintLabelWidth = TypefaceUtils.getStringWidth(hintLabel, paint); hintX = keyWidth - mKeyHintLetterPadding - - Math.max(keyNumericHintLabelReferenceCharWidth, keyHintLabelStringWidth) - / 2.0f; + - Math.max(hintDigitWidth, hintLabelWidth) / 2.0f; hintY = -paint.ascent(); paint.setTextAlign(Align.CENTER); } - canvas.drawText(hintLabel, 0, hintLabel.length(), hintX, hintY, paint); + canvas.drawText(hintLabel, 0, hintLabel.length(), hintX, hintY + adjustmentY, paint); if (LatinImeLogger.sVISUALDEBUG) { final Paint line = new Paint(); @@ -530,7 +530,7 @@ public class KeyboardView extends View { paint.setColor(params.mHintLabelColor); paint.setTextAlign(Align.CENTER); final float hintX = keyWidth - mKeyHintLetterPadding - - TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f; + - TypefaceUtils.getReferenceCharWidth(paint) / 2.0f; final float hintY = keyHeight - mKeyPopupHintLetterPadding; canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint); diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 13db47004..a638b238c 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -1193,7 +1193,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) { final int maxTextWidth = width - mLanguageOnSpacebarHorizontalMargin * 2; paint.setTextScaleX(1.0f); - final float textWidth = TypefaceUtils.getLabelWidth(text, paint); + final float textWidth = TypefaceUtils.getStringWidth(text, paint); if (textWidth < width) { return true; } @@ -1204,7 +1204,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } paint.setTextScaleX(scaleX); - return TypefaceUtils.getLabelWidth(text, paint) < maxTextWidth; + return TypefaceUtils.getStringWidth(text, paint) < maxTextWidth; } // Layout language name on spacebar. diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 8256d4623..385123998 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -327,7 +327,7 @@ public final class MoreKeysKeyboard extends Keyboard { // If the label is single letter, minKeyWidth is enough to hold the label. if (label != null && StringUtils.codePointCount(label) > 1) { maxWidth = Math.max(maxWidth, - (int)(TypefaceUtils.getLabelWidth(label, paint) + padding)); + (int)(TypefaceUtils.getStringWidth(label, paint) + padding)); } } return maxWidth; diff --git a/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java index 9cf68d43d..5a996ff53 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/ScrollKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java @@ -20,25 +20,21 @@ import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; -import android.widget.ScrollView; -import android.widget.Scroller; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardView; +import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.latin.R; /** - * This is an extended {@link KeyboardView} class that hosts a vertical scroll keyboard. + * This is an extended {@link KeyboardView} class that hosts an emoji page keyboard. * Multi-touch unsupported. No {@link PointerTracker}s. No gesture support. - * TODO: Vertical scroll capability should be removed from this class because it's no longer used. */ // TODO: Implement key popup preview. -public final class ScrollKeyboardView extends KeyboardView implements - ScrollViewWithNotifier.ScrollListener, GestureDetector.OnGestureListener { - private static final boolean PAGINATION = false; - +public final class EmojiPageKeyboardView extends KeyboardView implements + GestureDetector.OnGestureListener { public interface OnKeyClickListener { public void onKeyClick(Key key); } @@ -52,63 +48,15 @@ public final class ScrollKeyboardView extends KeyboardView implements private final KeyDetector mKeyDetector = new KeyDetector(0.0f /*keyHysteresisDistance */); private final GestureDetector mGestureDetector; - private final Scroller mScroller; - private ScrollViewWithNotifier mScrollView; - - public ScrollKeyboardView(final Context context, final AttributeSet attrs) { + public EmojiPageKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); } - public ScrollKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) { + public EmojiPageKeyboardView(final Context context, final AttributeSet attrs, + final int defStyle) { super(context, attrs, defStyle); mGestureDetector = new GestureDetector(context, this); mGestureDetector.setIsLongpressEnabled(false /* isLongpressEnabled */); - mScroller = new Scroller(context); - } - - public void setScrollView(final ScrollViewWithNotifier scrollView) { - mScrollView = scrollView; - scrollView.setScrollListener(this); - } - - private final Runnable mScrollTask = new Runnable() { - @Override - public void run() { - final Scroller scroller = mScroller; - final ScrollView scrollView = mScrollView; - scroller.computeScrollOffset(); - scrollView.scrollTo(0, scroller.getCurrY()); - if (!scroller.isFinished()) { - scrollView.post(this); - } - } - }; - - // {@link ScrollViewWithNotified#ScrollListener} methods. - @Override - public void notifyScrollChanged(final int scrollX, final int scrollY, final int oldX, - final int oldY) { - if (PAGINATION) { - mScroller.forceFinished(true /* finished */); - mScrollView.removeCallbacks(mScrollTask); - final int currentTop = mScrollView.getScrollY(); - final int pageHeight = getKeyboard().mBaseHeight; - final int lastPageNo = currentTop / pageHeight; - final int lastPageTop = lastPageNo * pageHeight; - final int nextPageNo = lastPageNo + 1; - final int nextPageTop = Math.min(nextPageNo * pageHeight, getHeight() - pageHeight); - final int scrollTo = (currentTop - lastPageTop) < (nextPageTop - currentTop) - ? lastPageTop : nextPageTop; - final int deltaY = scrollTo - currentTop; - mScroller.startScroll(0, currentTop, 0, deltaY, 300); - mScrollView.post(mScrollTask); - } - } - - @Override - public void notifyOverScrolled(final int scrollX, final int scrollY, final boolean clampedX, - final boolean clampedY) { - releaseCurrentKey(); } public void setOnKeyClickListener(final OnKeyClickListener listener) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java index 05d855e31..f7e43a6c2 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java @@ -27,6 +27,7 @@ import com.android.inputmethod.latin.utils.XmlParseUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import java.util.Arrays; import java.util.HashMap; public final class KeyStylesSet { @@ -90,7 +91,8 @@ public final class KeyStylesSet { } final Object value = mStyleAttributes.get(index); if (value != null) { - return (String[])value; + final String[] array = (String[])value; + return Arrays.copyOf(array, array.length); } final KeyStyle parentStyle = mStyles.get(mParentStyleName); return parentStyle.getStringArray(a, index); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java index 8bdad364c..c3e0aa685 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java @@ -47,6 +47,8 @@ public final class KeyVisualAttributes { public final int mShiftedLetterHintActivatedColor; public final int mPreviewTextColor; + public final float mHintLabelVerticalAdjustment; + private static final int[] VISUAL_ATTRIBUTE_IDS = { R.styleable.Keyboard_Key_keyTypeface, R.styleable.Keyboard_Key_keyLetterSize, @@ -65,6 +67,7 @@ public final class KeyVisualAttributes { R.styleable.Keyboard_Key_keyShiftedLetterHintInactivatedColor, R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor, R.styleable.Keyboard_Key_keyPreviewTextColor, + R.styleable.Keyboard_Key_keyHintLabelVerticalAdjustment, }; private static final SparseIntArray sVisualAttributeIds = new SparseIntArray(); private static final int ATTR_DEFINED = 1; @@ -127,5 +130,8 @@ public final class KeyVisualAttributes { mShiftedLetterHintActivatedColor = keyAttr.getColor( R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor, 0); mPreviewTextColor = keyAttr.getColor(R.styleable.Keyboard_Key_keyPreviewTextColor, 0); + + mHintLabelVerticalAdjustment = ResourceUtils.getFraction(keyAttr, + R.styleable.Keyboard_Key_keyHintLabelVerticalAdjustment, 0.0f); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java index e769e3cdd..b3975dc50 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java @@ -87,11 +87,11 @@ public final class KeyboardTextsSet { return (text == null) ? LANGUAGE_DEFAULT[id] : text; } + // These texts' name should be aligned with the @string/<name> in + // values*/strings-action-keys.xml. private static final String[] RESOURCE_NAMES = { - // These texts' name should be aligned with the @string/<name> in values/strings.xml. // Labels for action. "label_go_key", - // "label_search_key", "label_send_key", "label_next_key", "label_done_key", @@ -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!8,;,/,(,),#,!,\\,,?,&,\\%,+,\",-,:,',@", // 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!9,;,/,(,),#,\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 */ "!fixedColumnOrder!8,;,/,(|),)|(,#,!,\\,,?,&,\\%,+,\",-,:,',@", // 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/keyboard/internal/ScrollViewWithNotifier.java b/java/src/com/android/inputmethod/keyboard/internal/ScrollViewWithNotifier.java deleted file mode 100644 index d1ccdc7b5..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/ScrollViewWithNotifier.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.ScrollView; - -/** - * This is an extended {@link ScrollView} that can notify - * {@link ScrollView#onScrollChanged(int,int,int,int} and - * {@link ScrollView#onOverScrolled(int,int,int,int)} to a content view. - */ -public class ScrollViewWithNotifier extends ScrollView { - private ScrollListener mScrollListener = EMPTY_LISTER; - - public interface ScrollListener { - public void notifyScrollChanged(int scrollX, int scrollY, int oldX, int oldY); - public void notifyOverScrolled(int scrollX, int scrollY, boolean clampedX, - boolean clampedY); - } - - private static final ScrollListener EMPTY_LISTER = new ScrollListener() { - @Override - public void notifyScrollChanged(int scrollX, int scrollY, int oldX, int oldY) {} - @Override - public void notifyOverScrolled(int scrollX, int scrollY, boolean clampedX, - boolean clampedY) {} - }; - - public ScrollViewWithNotifier(final Context context, final AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onScrollChanged(final int scrollX, final int scrollY, final int oldX, - final int oldY) { - super.onScrollChanged(scrollX, scrollY, oldX, oldY); - mScrollListener.notifyScrollChanged(scrollX, scrollY, oldX, oldY); - } - - @Override - protected void onOverScrolled(final int scrollX, final int scrollY, final boolean clampedX, - final boolean clampedY) { - super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); - mScrollListener.notifyOverScrolled(scrollX, scrollY, clampedX, clampedY); - } - - public void setScrollListener(final ScrollListener listener) { - mScrollListener = listener; - } -} 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/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index eb8650e6f..d059cc8a9 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -23,7 +23,6 @@ import android.util.Log; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.makedict.FormatSpec; -import com.android.inputmethod.latin.personalization.DynamicPersonalizationDictionaryWriter; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.CollectionUtils; @@ -53,10 +52,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** Whether to print debug output to log */ private static boolean DEBUG = false; - // TODO: Remove. - /** Whether to call binary dictionary dynamically updating methods. */ - public static boolean ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE = true; - private static final int TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS = 100; /** @@ -164,11 +159,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private static AbstractDictionaryWriter getDictionaryWriter(final Context context, final String dictType, final boolean isDynamicPersonalizationDictionary) { if (isDynamicPersonalizationDictionary) { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - return null; - } else { - return new DynamicPersonalizationDictionaryWriter(context, dictType); - } + return null; } else { return new DictionaryWriter(context, dictType); } @@ -244,7 +235,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE && mDictionaryWriter == null) { + if (mDictionaryWriter == null) { mBinaryDictionary.close(); final File file = new File(mContext.getFilesDir(), mFilename); BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), @@ -286,7 +277,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * Check whether GC is needed and run GC if required. */ protected void runGCIfRequired(final boolean mindsBlockByGC) { - if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) return; getExecutor(mFilename).execute(new Runnable() { @Override public void run() { @@ -296,7 +286,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } private void runGCIfRequiredInternalLocked(final boolean mindsBlockByGC) { - if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) return; // Calls to needsToRunGC() need to be serialized. if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { if (setIsRegeneratingIfNotRegenerating()) { @@ -327,14 +316,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.addUnigramWord(word, frequency); - } else { - // TODO: Remove. - mDictionaryWriter.addUnigramWord(word, shortcutTarget, frequency, shortcutFreq, - isNotAWord); - } + runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); + mBinaryDictionary.addUnigramWord(word, frequency); } }); } @@ -352,14 +335,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.addBigramWords(word0, word1, frequency); - } else { - // TODO: Remove. - mDictionaryWriter.addBigramWords(word0, word1, frequency, isValid, - 0 /* lastTouchedTime */); - } + runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); + mBinaryDictionary.addBigramWords(word0, word1, frequency); } }); } @@ -376,13 +353,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { getExecutor(mFilename).execute(new Runnable() { @Override public void run() { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); - mBinaryDictionary.removeBigramWords(word0, word1); - } else { - // TODO: Remove. - mDictionaryWriter.removeBigramWords(word0, word1); - } + runGCIfRequiredInternalLocked(true /* mindsBlockByGC */); + mBinaryDictionary.removeBigramWords(word0, word1); } }); } @@ -396,46 +368,20 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { if (isRegenerating()) { return null; } - final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList(); final AsyncResultHolder<ArrayList<SuggestedWordInfo>> holder = new AsyncResultHolder<ArrayList<SuggestedWordInfo>>(); getExecutor(mFilename).executePrioritized(new Runnable() { @Override public void run() { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - if (mBinaryDictionary == null) { - holder.set(null); - return; - } - final ArrayList<SuggestedWordInfo> binarySuggestion = - mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord, - proximityInfo, blockOffensiveWords, additionalFeaturesOptions, - sessionId); - holder.set(binarySuggestion); - } else { - final ArrayList<SuggestedWordInfo> inMemDictSuggestion = - composer.isBatchMode() ? null : - mDictionaryWriter.getSuggestionsWithSessionId(composer, - prevWord, proximityInfo, blockOffensiveWords, - additionalFeaturesOptions, sessionId); - // TODO: Remove checking mIsUpdatable and use native suggestion. - if (mBinaryDictionary != null && !mIsUpdatable) { - final ArrayList<SuggestedWordInfo> binarySuggestion = - mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord, - proximityInfo, blockOffensiveWords, - additionalFeaturesOptions, sessionId); - if (inMemDictSuggestion == null) { - holder.set(binarySuggestion); - } else if (binarySuggestion == null) { - holder.set(inMemDictSuggestion); - } else { - binarySuggestion.addAll(inMemDictSuggestion); - holder.set(binarySuggestion); - } - } else { - holder.set(inMemDictSuggestion); - } + if (mBinaryDictionary == null) { + holder.set(null); + return; } + final ArrayList<SuggestedWordInfo> binarySuggestion = + mBinaryDictionary.getSuggestionsWithSessionId(composer, prevWord, + proximityInfo, blockOffensiveWords, additionalFeaturesOptions, + sessionId); + holder.set(binarySuggestion); } }); return holder.get(null, TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS); @@ -542,20 +488,16 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { loadDictionaryAsync(); mDictionaryWriter.write(mFilename, getHeaderAttributeMap()); } else { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - if (mBinaryDictionary == null || !mBinaryDictionary.isValidDictionary()) { - final File file = new File(mContext.getFilesDir(), mFilename); - BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), - DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap()); + if (mBinaryDictionary == null || !mBinaryDictionary.isValidDictionary()) { + final File file = new File(mContext.getFilesDir(), mFilename); + BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), + DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap()); + } else { + if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { + mBinaryDictionary.flushWithGC(); } else { - if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { - mBinaryDictionary.flushWithGC(); - } else { - mBinaryDictionary.flush(); - } + mBinaryDictionary.flush(); } - } else { - mDictionaryWriter.write(mFilename, getHeaderAttributeMap()); } } } @@ -663,20 +605,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } /** - * Load the dictionary to memory. - */ - protected void asyncLoadDictionaryToMemory() { - getExecutor(mFilename).executePrioritized(new Runnable() { - @Override - public void run() { - if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - loadDictionaryAsync(); - } - } - }); - } - - /** * Generate binary dictionary using DictionaryWriter. */ protected void asyncFlashAllBinaryDictionary() { @@ -704,7 +632,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } } - // TODO: Implement native binary methods once the dynamic dictionary implementation is done. + // TODO: Implement BinaryDictionary.isInDictionary(). @UsedForTesting public boolean isInDictionaryForTests(final String word) { final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<Boolean>(); @@ -712,12 +640,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @Override public void run() { if (mDictType == Dictionary.TYPE_USER_HISTORY) { - if (ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - holder.set(mBinaryDictionary.isValidWord(word)); - } else { - holder.set(((DynamicPersonalizationDictionaryWriter) mDictionaryWriter) - .isInBigramListForTests(word)); - } + holder.set(mBinaryDictionary.isValidWord(word)); } } }); @@ -733,4 +656,19 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { public boolean isTerminatedForTests() { return getExecutor(mFilename).isTerminated(); } + + @UsedForTesting + protected void runAfterGcForDebug(final Runnable r) { + getExecutor(mFilename).executePrioritized(new Runnable() { + @Override + public void run() { + try { + mBinaryDictionary.flushWithGC(); + r.run(); + } finally { + mFilenameDictionaryUpdateController.mIsRegenerating.set(false); + } + } + }); + } } diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java deleted file mode 100644 index 95c9bcab9..000000000 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ /dev/null @@ -1,894 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin; - -import android.text.TextUtils; -import android.util.Log; - -import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; -import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils.ForgettingCurveParams; - -import java.util.ArrayList; -import java.util.LinkedList; - -/** - * Class for an in-memory dictionary that can grow dynamically and can - * be searched for suggestions and valid words. - */ -// TODO: Remove after binary dictionary supports dynamic update. -public class ExpandableDictionary extends Dictionary { - private static final String TAG = ExpandableDictionary.class.getSimpleName(); - /** - * The weight to give to a word if it's length is the same as the number of typed characters. - */ - private static final int FULL_WORD_SCORE_MULTIPLIER = 2; - - private char[] mWordBuilder = new char[Constants.DICTIONARY_MAX_WORD_LENGTH]; - private int mMaxDepth; - private int mInputLength; - - private static final class Node { - char mCode; - int mFrequency; - boolean mTerminal; - Node mParent; - NodeArray mChildren; - ArrayList<char[]> mShortcutTargets; - boolean mShortcutOnly; - LinkedList<NextWord> mNGrams; // Supports ngram - } - - private static final class NodeArray { - Node[] mData; - int mLength = 0; - private static final int INCREMENT = 2; - - NodeArray() { - mData = new Node[INCREMENT]; - } - - void add(final Node n) { - if (mLength + 1 > mData.length) { - Node[] tempData = new Node[mLength + INCREMENT]; - if (mLength > 0) { - System.arraycopy(mData, 0, tempData, 0, mLength); - } - mData = tempData; - } - mData[mLength++] = n; - } - } - - public interface NextWord { - public Node getWordNode(); - public int getFrequency(); - public ForgettingCurveParams getFcParams(); - public int notifyTypedAgainAndGetFrequency(); - } - - private static final class NextStaticWord implements NextWord { - public final Node mWord; - private final int mFrequency; - public NextStaticWord(Node word, int frequency) { - mWord = word; - mFrequency = frequency; - } - - @Override - public Node getWordNode() { - return mWord; - } - - @Override - public int getFrequency() { - return mFrequency; - } - - @Override - public ForgettingCurveParams getFcParams() { - return null; - } - - @Override - public int notifyTypedAgainAndGetFrequency() { - return mFrequency; - } - } - - private static final class NextHistoryWord implements NextWord { - public final Node mWord; - public final ForgettingCurveParams mFcp; - - public NextHistoryWord(Node word, ForgettingCurveParams fcp) { - mWord = word; - mFcp = fcp; - } - - @Override - public Node getWordNode() { - return mWord; - } - - @Override - public int getFrequency() { - return mFcp.getFrequency(); - } - - @Override - public ForgettingCurveParams getFcParams() { - return mFcp; - } - - @Override - public int notifyTypedAgainAndGetFrequency() { - return mFcp.notifyTypedAgainAndGetFrequency(); - } - } - - private NodeArray mRoots; - - private int[][] mCodes; - - public ExpandableDictionary(final String dictType) { - super(dictType); - clearDictionary(); - mCodes = new int[Constants.DICTIONARY_MAX_WORD_LENGTH][]; - } - - public int getMaxWordLength() { - return Constants.DICTIONARY_MAX_WORD_LENGTH; - } - - /** - * Add a word with an optional shortcut to the dictionary. - * @param word The word to add. - * @param shortcutTarget A shortcut target for this word, or null if none. - * @param frequency The frequency for this unigram. - * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored - * if shortcutTarget is null. - */ - public void addWord(final String word, final String shortcutTarget, final int frequency, - final int shortcutFreq) { - if (word.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH) { - return; - } - addWordRec(mRoots, word, 0, shortcutTarget, frequency, shortcutFreq, null); - } - - /** - * Add a word, recursively searching for its correct place in the trie tree. - * @param children The node to recursively search for addition. Initially, the root of the tree. - * @param word The word to add. - * @param depth The current depth in the tree. - * @param shortcutTarget A shortcut target for this word, or null if none. - * @param frequency The frequency for this unigram. - * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored - * if shortcutTarget is null. - * @param parentNode The parent node, for up linking. Initially null, as the root has no parent. - */ - private void addWordRec(final NodeArray children, final String word, final int depth, - final String shortcutTarget, final int frequency, final int shortcutFreq, - final Node parentNode) { - final int wordLength = word.length(); - if (wordLength <= depth) return; - final char c = word.charAt(depth); - // Does children have the current character? - final int childrenLength = children.mLength; - Node childNode = null; - for (int i = 0; i < childrenLength; i++) { - final Node node = children.mData[i]; - if (node.mCode == c) { - childNode = node; - break; - } - } - final boolean isShortcutOnly = (null != shortcutTarget); - if (childNode == null) { - childNode = new Node(); - childNode.mCode = c; - childNode.mParent = parentNode; - childNode.mShortcutOnly = isShortcutOnly; - children.add(childNode); - } - if (wordLength == depth + 1) { - // Terminate this word - childNode.mTerminal = true; - if (isShortcutOnly) { - if (null == childNode.mShortcutTargets) { - childNode.mShortcutTargets = CollectionUtils.newArrayList(); - } - childNode.mShortcutTargets.add(shortcutTarget.toCharArray()); - } else { - childNode.mShortcutOnly = false; - } - childNode.mFrequency = Math.max(frequency, childNode.mFrequency); - if (childNode.mFrequency > 255) childNode.mFrequency = 255; - return; - } - if (childNode.mChildren == null) { - childNode.mChildren = new NodeArray(); - } - addWordRec(childNode.mChildren, word, depth + 1, shortcutTarget, frequency, shortcutFreq, - childNode); - } - - @Override - public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, - final boolean blockOffensiveWords, final int[] additionalFeaturesOptions) { - if (composer.size() > 1) { - if (composer.size() >= Constants.DICTIONARY_MAX_WORD_LENGTH) { - return null; - } - final ArrayList<SuggestedWordInfo> suggestions = - getWordsInner(composer, prevWord, proximityInfo); - return suggestions; - } else { - if (TextUtils.isEmpty(prevWord)) return null; - final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList(); - runBigramReverseLookUp(prevWord, suggestions); - return suggestions; - } - } - - private ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes, - final String prevWordForBigrams, final ProximityInfo proximityInfo) { - final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList(); - mInputLength = codes.size(); - if (mCodes.length < mInputLength) mCodes = new int[mInputLength][]; - final InputPointers ips = codes.getInputPointers(); - final int[] xCoordinates = ips.getXCoordinates(); - final int[] yCoordinates = ips.getYCoordinates(); - // Cache the codes so that we don't have to lookup an array list - for (int i = 0; i < mInputLength; i++) { - // TODO: Calculate proximity info here. - if (mCodes[i] == null || mCodes[i].length < 1) { - mCodes[i] = new int[ProximityInfo.MAX_PROXIMITY_CHARS_SIZE]; - } - final int x = xCoordinates != null && i < xCoordinates.length ? - xCoordinates[i] : Constants.NOT_A_COORDINATE; - final int y = xCoordinates != null && i < yCoordinates.length ? - yCoordinates[i] : Constants.NOT_A_COORDINATE; - proximityInfo.fillArrayWithNearestKeyCodes(x, y, codes.getCodeAt(i), mCodes[i]); - } - mMaxDepth = mInputLength * 3; - getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, suggestions); - for (int i = 0; i < mInputLength; i++) { - getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, suggestions); - } - return suggestions; - } - - @Override - public synchronized boolean isValidWord(final String word) { - final Node node = searchNode(mRoots, word, 0, word.length()); - // If node is null, we didn't find the word, so it's not valid. - // If node.mShortcutOnly is true, then it exists as a shortcut but not as a word, - // so that means it's not a valid word. - // If node.mShortcutOnly is false, then it exists as a word (it may also exist as - // a shortcut, but this does not matter), so it's a valid word. - return (node == null) ? false : !node.mShortcutOnly; - } - - public boolean removeBigram(final String word0, final String word1) { - // Refer to addOrSetBigram() about word1.toLowerCase() - final Node firstWord = searchWord(mRoots, word0.toLowerCase(), 0, null); - final Node secondWord = searchWord(mRoots, word1, 0, null); - LinkedList<NextWord> bigrams = firstWord.mNGrams; - NextWord bigramNode = null; - if (bigrams == null || bigrams.size() == 0) { - return false; - } else { - for (NextWord nw : bigrams) { - if (nw.getWordNode() == secondWord) { - bigramNode = nw; - break; - } - } - } - if (bigramNode == null) { - return false; - } - return bigrams.remove(bigramNode); - } - - /** - * Returns the word's frequency or -1 if not found - */ - @UsedForTesting - public int getWordFrequency(final String word) { - // Case-sensitive search - final Node node = searchNode(mRoots, word, 0, word.length()); - return (node == null) ? -1 : node.mFrequency; - } - - public NextWord getBigramWord(final String word0, final String word1) { - // Refer to addOrSetBigram() about word0.toLowerCase() - final Node firstWord = searchWord(mRoots, word0.toLowerCase(), 0, null); - final Node secondWord = searchWord(mRoots, word1, 0, null); - LinkedList<NextWord> bigrams = firstWord.mNGrams; - if (bigrams == null || bigrams.size() == 0) { - return null; - } else { - for (NextWord nw : bigrams) { - if (nw.getWordNode() == secondWord) { - return nw; - } - } - } - return null; - } - - private static int computeSkippedWordFinalFreq(final int freq, final int snr, - final int inputLength) { - // The computation itself makes sense for >= 2, but the == 2 case returns 0 - // anyway so we may as well test against 3 instead and return the constant - if (inputLength >= 3) { - return (freq * snr * (inputLength - 2)) / (inputLength - 1); - } else { - return 0; - } - } - - /** - * Helper method to add a word and its shortcuts. - * - * @param node the terminal node - * @param word the word to insert, as an array of code points - * @param depth the depth of the node in the tree - * @param finalFreq the frequency for this word - * @param suggestions the suggestion collection to add the suggestions to - * @return whether there is still space for more words. - */ - private boolean addWordAndShortcutsFromNode(final Node node, final char[] word, final int depth, - final int finalFreq, final ArrayList<SuggestedWordInfo> suggestions) { - if (finalFreq > 0 && !node.mShortcutOnly) { - // Use KIND_CORRECTION always. This dictionary does not really have a notion of - // COMPLETION against CORRECTION; we could artificially add one by looking at - // the respective size of the typed word and the suggestion if it matters sometime - // in the future. - suggestions.add(new SuggestedWordInfo(new String(word, 0, depth + 1), finalFreq, - SuggestedWordInfo.KIND_CORRECTION, this /* sourceDict */, - SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, - SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); - if (suggestions.size() >= Suggest.MAX_SUGGESTIONS) return false; - } - if (null != node.mShortcutTargets) { - final int length = node.mShortcutTargets.size(); - for (int shortcutIndex = 0; shortcutIndex < length; ++shortcutIndex) { - final char[] shortcut = node.mShortcutTargets.get(shortcutIndex); - suggestions.add(new SuggestedWordInfo(new String(shortcut, 0, shortcut.length), - finalFreq, SuggestedWordInfo.KIND_SHORTCUT, this /* sourceDict */, - SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, - SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); - if (suggestions.size() > Suggest.MAX_SUGGESTIONS) return false; - } - } - return true; - } - - /** - * Recursively traverse the tree for words that match the input. Input consists of - * a list of arrays. Each item in the list is one input character position. An input - * character is actually an array of multiple possible candidates. This function is not - * optimized for speed, assuming that the user dictionary will only be a few hundred words in - * size. - * @param roots node whose children have to be search for matches - * @param codes the input character codes - * @param word the word being composed as a possible match - * @param depth the depth of traversal - the length of the word being composed thus far - * @param completion whether the traversal is now in completion mode - meaning that we've - * exhausted the input and we're looking for all possible suffixes. - * @param snr current weight of the word being formed - * @param inputIndex position in the input characters. This can be off from the depth in - * case we skip over some punctuations such as apostrophe in the traversal. That is, if you type - * "wouldve", it could be matching "would've", so the depth will be one more than the - * inputIndex - * @param suggestions the list in which to add suggestions - */ - // TODO: Share this routine with the native code for BinaryDictionary - private void getWordsRec(final NodeArray roots, final WordComposer codes, final char[] word, - final int depth, final boolean completion, final int snr, final int inputIndex, - final int skipPos, final ArrayList<SuggestedWordInfo> suggestions) { - final int count = roots.mLength; - final int codeSize = mInputLength; - // Optimization: Prune out words that are too long compared to how much was typed. - if (depth > mMaxDepth) { - return; - } - final int[] currentChars; - if (codeSize <= inputIndex) { - currentChars = null; - } else { - currentChars = mCodes[inputIndex]; - } - - for (int i = 0; i < count; i++) { - final Node node = roots.mData[i]; - final char c = node.mCode; - final char lowerC = toLowerCase(c); - final boolean terminal = node.mTerminal; - final NodeArray children = node.mChildren; - final int freq = node.mFrequency; - if (completion || currentChars == null) { - word[depth] = c; - if (terminal) { - final int finalFreq; - if (skipPos < 0) { - finalFreq = freq * snr; - } else { - finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength); - } - if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, suggestions)) { - // No space left in the queue, bail out - return; - } - } - if (children != null) { - getWordsRec(children, codes, word, depth + 1, true, snr, inputIndex, - skipPos, suggestions); - } - } else if ((c == Constants.CODE_SINGLE_QUOTE - && currentChars[0] != Constants.CODE_SINGLE_QUOTE) || depth == skipPos) { - // Skip the ' and continue deeper - word[depth] = c; - if (children != null) { - getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, - skipPos, suggestions); - } - } else { - // Don't use alternatives if we're looking for missing characters - final int alternativesSize = skipPos >= 0 ? 1 : currentChars.length; - for (int j = 0; j < alternativesSize; j++) { - final int addedAttenuation = (j > 0 ? 1 : 2); - final int currentChar = currentChars[j]; - if (currentChar == Constants.NOT_A_CODE) { - break; - } - if (currentChar == lowerC || currentChar == c) { - word[depth] = c; - - if (codeSize == inputIndex + 1) { - if (terminal) { - final int finalFreq; - if (skipPos < 0) { - finalFreq = freq * snr * addedAttenuation - * FULL_WORD_SCORE_MULTIPLIER; - } else { - finalFreq = computeSkippedWordFinalFreq(freq, - snr * addedAttenuation, mInputLength); - } - if (!addWordAndShortcutsFromNode(node, word, depth, finalFreq, - suggestions)) { - // No space left in the queue, bail out - return; - } - } - if (children != null) { - getWordsRec(children, codes, word, depth + 1, - true, snr * addedAttenuation, inputIndex + 1, - skipPos, suggestions); - } - } else if (children != null) { - getWordsRec(children, codes, word, depth + 1, - false, snr * addedAttenuation, inputIndex + 1, - skipPos, suggestions); - } - } - } - } - } - } - - public int setBigramAndGetFrequency(final String word0, final String word1, - final int frequency) { - return setBigramAndGetFrequency(word0, word1, frequency, null /* unused */); - } - - public int setBigramAndGetFrequency(final String word0, final String word1, - final ForgettingCurveParams fcp) { - return setBigramAndGetFrequency(word0, word1, 0 /* unused */, fcp); - } - - /** - * Adds bigrams to the in-memory trie structure that is being used to retrieve any word - * @param word0 the first word of this bigram - * @param word1 the second word of this bigram - * @param frequency frequency for this bigram - * @param fcp an instance of ForgettingCurveParams to use for decay policy - * @return returns the final bigram frequency - */ - private int setBigramAndGetFrequency(final String word0, final String word1, - final int frequency, final ForgettingCurveParams fcp) { - if (TextUtils.isEmpty(word0)) { - Log.e(TAG, "Invalid bigram previous word: " + word0); - return frequency; - } - // We don't want results to be different according to case of the looked up left hand side - // word. We do want however to return the correct case for the right hand side. - // So we want to squash the case of the left hand side, and preserve that of the right - // hand side word. - final String word0Lower = word0.toLowerCase(); - if (TextUtils.isEmpty(word0Lower) || TextUtils.isEmpty(word1)) { - Log.e(TAG, "Invalid bigram pair: " + word0 + ", " + word0Lower + ", " + word1); - return frequency; - } - final Node firstWord = searchWord(mRoots, word0Lower, 0, null); - final Node secondWord = searchWord(mRoots, word1, 0, null); - LinkedList<NextWord> bigrams = firstWord.mNGrams; - if (bigrams == null || bigrams.size() == 0) { - firstWord.mNGrams = CollectionUtils.newLinkedList(); - bigrams = firstWord.mNGrams; - } else { - for (NextWord nw : bigrams) { - if (nw.getWordNode() == secondWord) { - return nw.notifyTypedAgainAndGetFrequency(); - } - } - } - if (fcp != null) { - // history - firstWord.mNGrams.add(new NextHistoryWord(secondWord, fcp)); - } else { - firstWord.mNGrams.add(new NextStaticWord(secondWord, frequency)); - } - return frequency; - } - - /** - * Searches for the word and add the word if it does not exist. - * @return Returns the terminal node of the word we are searching for. - */ - private Node searchWord(final NodeArray children, final String word, final int depth, - final Node parentNode) { - final int wordLength = word.length(); - final char c = word.charAt(depth); - // Does children have the current character? - final int childrenLength = children.mLength; - Node childNode = null; - for (int i = 0; i < childrenLength; i++) { - final Node node = children.mData[i]; - if (node.mCode == c) { - childNode = node; - break; - } - } - if (childNode == null) { - childNode = new Node(); - childNode.mCode = c; - childNode.mParent = parentNode; - children.add(childNode); - } - if (wordLength == depth + 1) { - // Terminate this word - childNode.mTerminal = true; - return childNode; - } - if (childNode.mChildren == null) { - childNode.mChildren = new NodeArray(); - } - return searchWord(childNode.mChildren, word, depth + 1, childNode); - } - - private void runBigramReverseLookUp(final String previousWord, - final ArrayList<SuggestedWordInfo> suggestions) { - // Search for the lowercase version of the word only, because that's where bigrams - // store their sons. - final Node prevWord = searchNode(mRoots, previousWord.toLowerCase(), 0, - previousWord.length()); - if (prevWord != null && prevWord.mNGrams != null) { - reverseLookUp(prevWord.mNGrams, suggestions); - } - } - - // Local to reverseLookUp, but do not allocate each time. - private final char[] mLookedUpString = new char[Constants.DICTIONARY_MAX_WORD_LENGTH]; - - /** - * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words - * to the suggestions list passed as an argument. - * @param terminalNodes list of terminal nodes we want to add - * @param suggestions the suggestion collection to add the word to - */ - private void reverseLookUp(final LinkedList<NextWord> terminalNodes, - final ArrayList<SuggestedWordInfo> suggestions) { - Node node; - int freq; - for (NextWord nextWord : terminalNodes) { - node = nextWord.getWordNode(); - freq = nextWord.getFrequency(); - int index = Constants.DICTIONARY_MAX_WORD_LENGTH; - do { - --index; - mLookedUpString[index] = node.mCode; - node = node.mParent; - } while (node != null && index > 0); - - // If node is null, we have a word longer than MAX_WORD_LENGTH in the dictionary. - // It's a little unclear how this can happen, but just in case it does it's safer - // to ignore the word in this case. - if (freq >= 0 && node == null) { - suggestions.add(new SuggestedWordInfo(new String(mLookedUpString, index, - Constants.DICTIONARY_MAX_WORD_LENGTH - index), - freq, SuggestedWordInfo.KIND_CORRECTION, this /* sourceDict */, - SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, - SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); - } - } - } - - /** - * Recursively search for the terminal node of the word. - * - * One iteration takes the full word to search for and the current index of the recursion. - * - * @param children the node of the trie to search under. - * @param word the word to search for. Only read [offset..length] so there may be trailing chars - * @param offset the index in {@code word} this recursion should operate on. - * @param length the length of the input word. - * @return Returns the terminal node of the word if the word exists - */ - private Node searchNode(final NodeArray children, final CharSequence word, final int offset, - final int length) { - final int count = children.mLength; - final char currentChar = word.charAt(offset); - for (int j = 0; j < count; j++) { - final Node node = children.mData[j]; - if (node.mCode == currentChar) { - if (offset == length - 1) { - if (node.mTerminal) { - return node; - } - } else { - if (node.mChildren != null) { - Node returnNode = searchNode(node.mChildren, word, offset + 1, length); - if (returnNode != null) return returnNode; - } - } - } - } - return null; - } - - public void clearDictionary() { - mRoots = new NodeArray(); - } - - private static char toLowerCase(final char c) { - char baseChar = c; - if (c < BASE_CHARS.length) { - baseChar = BASE_CHARS[c]; - } - if (baseChar >= 'A' && baseChar <= 'Z') { - return (char)(baseChar | 32); - } else if (baseChar > 127) { - return Character.toLowerCase(baseChar); - } - return baseChar; - } - - /** - * Table mapping most combined Latin, Greek, and Cyrillic characters - * to their base characters. If c is in range, BASE_CHARS[c] == c - * if c is not a combined character, or the base character if it - * is combined. - * - * cf. native/jni/src/utils/char_utils.cpp - */ - private static final char BASE_CHARS[] = { - /* U+0000 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - /* U+0008 */ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - /* U+0010 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - /* U+0018 */ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - /* U+0020 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - /* U+0028 */ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - /* U+0030 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - /* U+0038 */ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - /* U+0040 */ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - /* U+0048 */ 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - /* U+0050 */ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - /* U+0058 */ 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - /* U+0060 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - /* U+0068 */ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, - /* U+0070 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - /* U+0078 */ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, - /* U+0080 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - /* U+0088 */ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - /* U+0090 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - /* U+0098 */ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, - /* U+00A0 */ 0x0020, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - /* U+00A8 */ 0x0020, 0x00A9, 0x0061, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0020, - /* U+00B0 */ 0x00B0, 0x00B1, 0x0032, 0x0033, 0x0020, 0x03BC, 0x00B6, 0x00B7, - /* U+00B8 */ 0x0020, 0x0031, 0x006F, 0x00BB, 0x0031, 0x0031, 0x0033, 0x00BF, - /* U+00C0 */ 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00C6, 0x0043, - /* U+00C8 */ 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, - /* U+00D0 */ 0x00D0, 0x004E, 0x004F, 0x004F, 0x004F, 0x004F, 0x004F, 0x00D7, - /* U+00D8 */ 0x004F, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00DE, 0x0073, - // U+00D8: Manually changed from 00D8 to 004F - // TODO: Check if it's really acceptable to consider Ø a diacritical variant of O - // U+00DF: Manually changed from 00DF to 0073 - /* U+00E0 */ 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x00E6, 0x0063, - /* U+00E8 */ 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, - /* U+00F0 */ 0x00F0, 0x006E, 0x006F, 0x006F, 0x006F, 0x006F, 0x006F, 0x00F7, - /* U+00F8 */ 0x006F, 0x0075, 0x0075, 0x0075, 0x0075, 0x0079, 0x00FE, 0x0079, - // U+00F8: Manually changed from 00F8 to 006F - // TODO: Check if it's really acceptable to consider ø a diacritical variant of o - /* U+0100 */ 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063, - /* U+0108 */ 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064, - /* U+0110 */ 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, - /* U+0118 */ 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067, - /* U+0120 */ 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127, - /* U+0128 */ 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, - /* U+0130 */ 0x0049, 0x0131, 0x0049, 0x0069, 0x004A, 0x006A, 0x004B, 0x006B, - /* U+0138 */ 0x0138, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, 0x006C, 0x004C, - /* U+0140 */ 0x006C, 0x004C, 0x006C, 0x004E, 0x006E, 0x004E, 0x006E, 0x004E, - // U+0141: Manually changed from 0141 to 004C - // U+0142: Manually changed from 0142 to 006C - /* U+0148 */ 0x006E, 0x02BC, 0x014A, 0x014B, 0x004F, 0x006F, 0x004F, 0x006F, - /* U+0150 */ 0x004F, 0x006F, 0x0152, 0x0153, 0x0052, 0x0072, 0x0052, 0x0072, - /* U+0158 */ 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073, - /* U+0160 */ 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0166, 0x0167, - /* U+0168 */ 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, - /* U+0170 */ 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079, - /* U+0178 */ 0x0059, 0x005A, 0x007A, 0x005A, 0x007A, 0x005A, 0x007A, 0x0073, - /* U+0180 */ 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187, - /* U+0188 */ 0x0188, 0x0189, 0x018A, 0x018B, 0x018C, 0x018D, 0x018E, 0x018F, - /* U+0190 */ 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, - /* U+0198 */ 0x0198, 0x0199, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F, - /* U+01A0 */ 0x004F, 0x006F, 0x01A2, 0x01A3, 0x01A4, 0x01A5, 0x01A6, 0x01A7, - /* U+01A8 */ 0x01A8, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AD, 0x01AE, 0x0055, - /* U+01B0 */ 0x0075, 0x01B1, 0x01B2, 0x01B3, 0x01B4, 0x01B5, 0x01B6, 0x01B7, - /* U+01B8 */ 0x01B8, 0x01B9, 0x01BA, 0x01BB, 0x01BC, 0x01BD, 0x01BE, 0x01BF, - /* U+01C0 */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x0044, 0x0044, 0x0064, 0x004C, - /* U+01C8 */ 0x004C, 0x006C, 0x004E, 0x004E, 0x006E, 0x0041, 0x0061, 0x0049, - /* U+01D0 */ 0x0069, 0x004F, 0x006F, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, - // U+01D5: Manually changed from 00DC to 0055 - // U+01D6: Manually changed from 00FC to 0075 - // U+01D7: Manually changed from 00DC to 0055 - /* U+01D8 */ 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x01DD, 0x0041, 0x0061, - // U+01D8: Manually changed from 00FC to 0075 - // U+01D9: Manually changed from 00DC to 0055 - // U+01DA: Manually changed from 00FC to 0075 - // U+01DB: Manually changed from 00DC to 0055 - // U+01DC: Manually changed from 00FC to 0075 - // U+01DE: Manually changed from 00C4 to 0041 - // U+01DF: Manually changed from 00E4 to 0061 - /* U+01E0 */ 0x0041, 0x0061, 0x00C6, 0x00E6, 0x01E4, 0x01E5, 0x0047, 0x0067, - // U+01E0: Manually changed from 0226 to 0041 - // U+01E1: Manually changed from 0227 to 0061 - /* U+01E8 */ 0x004B, 0x006B, 0x004F, 0x006F, 0x004F, 0x006F, 0x01B7, 0x0292, - // U+01EC: Manually changed from 01EA to 004F - // U+01ED: Manually changed from 01EB to 006F - /* U+01F0 */ 0x006A, 0x0044, 0x0044, 0x0064, 0x0047, 0x0067, 0x01F6, 0x01F7, - /* U+01F8 */ 0x004E, 0x006E, 0x0041, 0x0061, 0x00C6, 0x00E6, 0x004F, 0x006F, - // U+01FA: Manually changed from 00C5 to 0041 - // U+01FB: Manually changed from 00E5 to 0061 - // U+01FE: Manually changed from 00D8 to 004F - // TODO: Check if it's really acceptable to consider Ø a diacritical variant of O - // U+01FF: Manually changed from 00F8 to 006F - // TODO: Check if it's really acceptable to consider ø a diacritical variant of o - /* U+0200 */ 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065, - /* U+0208 */ 0x0049, 0x0069, 0x0049, 0x0069, 0x004F, 0x006F, 0x004F, 0x006F, - /* U+0210 */ 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075, - /* U+0218 */ 0x0053, 0x0073, 0x0054, 0x0074, 0x021C, 0x021D, 0x0048, 0x0068, - /* U+0220 */ 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0041, 0x0061, - /* U+0228 */ 0x0045, 0x0065, 0x004F, 0x006F, 0x004F, 0x006F, 0x004F, 0x006F, - // U+022A: Manually changed from 00D6 to 004F - // U+022B: Manually changed from 00F6 to 006F - // U+022C: Manually changed from 00D5 to 004F - // U+022D: Manually changed from 00F5 to 006F - /* U+0230 */ 0x004F, 0x006F, 0x0059, 0x0079, 0x0234, 0x0235, 0x0236, 0x0237, - // U+0230: Manually changed from 022E to 004F - // U+0231: Manually changed from 022F to 006F - /* U+0238 */ 0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F, - /* U+0240 */ 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, - /* U+0248 */ 0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F, - /* U+0250 */ 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, - /* U+0258 */ 0x0258, 0x0259, 0x025A, 0x025B, 0x025C, 0x025D, 0x025E, 0x025F, - /* U+0260 */ 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, - /* U+0268 */ 0x0268, 0x0269, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x026F, - /* U+0270 */ 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, - /* U+0278 */ 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, - /* U+0280 */ 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, - /* U+0288 */ 0x0288, 0x0289, 0x028A, 0x028B, 0x028C, 0x028D, 0x028E, 0x028F, - /* U+0290 */ 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, - /* U+0298 */ 0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F, - /* U+02A0 */ 0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7, - /* U+02A8 */ 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF, - /* U+02B0 */ 0x0068, 0x0266, 0x006A, 0x0072, 0x0279, 0x027B, 0x0281, 0x0077, - /* U+02B8 */ 0x0079, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, - /* U+02C0 */ 0x02C0, 0x02C1, 0x02C2, 0x02C3, 0x02C4, 0x02C5, 0x02C6, 0x02C7, - /* U+02C8 */ 0x02C8, 0x02C9, 0x02CA, 0x02CB, 0x02CC, 0x02CD, 0x02CE, 0x02CF, - /* U+02D0 */ 0x02D0, 0x02D1, 0x02D2, 0x02D3, 0x02D4, 0x02D5, 0x02D6, 0x02D7, - /* U+02D8 */ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x02DE, 0x02DF, - /* U+02E0 */ 0x0263, 0x006C, 0x0073, 0x0078, 0x0295, 0x02E5, 0x02E6, 0x02E7, - /* U+02E8 */ 0x02E8, 0x02E9, 0x02EA, 0x02EB, 0x02EC, 0x02ED, 0x02EE, 0x02EF, - /* U+02F0 */ 0x02F0, 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, 0x02F7, - /* U+02F8 */ 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, 0x02FD, 0x02FE, 0x02FF, - /* U+0300 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, - /* U+0308 */ 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, - /* U+0310 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, - /* U+0318 */ 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, - /* U+0320 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, - /* U+0328 */ 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, - /* U+0330 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, - /* U+0338 */ 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, - /* U+0340 */ 0x0300, 0x0301, 0x0342, 0x0313, 0x0308, 0x0345, 0x0346, 0x0347, - /* U+0348 */ 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, - /* U+0350 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, - /* U+0358 */ 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, - /* U+0360 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, - /* U+0368 */ 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, - /* U+0370 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x02B9, 0x0375, 0x0376, 0x0377, - /* U+0378 */ 0x0378, 0x0379, 0x0020, 0x037B, 0x037C, 0x037D, 0x003B, 0x037F, - /* U+0380 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0020, 0x00A8, 0x0391, 0x00B7, - /* U+0388 */ 0x0395, 0x0397, 0x0399, 0x038B, 0x039F, 0x038D, 0x03A5, 0x03A9, - /* U+0390 */ 0x03CA, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - /* U+0398 */ 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - /* U+03A0 */ 0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - /* U+03A8 */ 0x03A8, 0x03A9, 0x0399, 0x03A5, 0x03B1, 0x03B5, 0x03B7, 0x03B9, - /* U+03B0 */ 0x03CB, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - /* U+03B8 */ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - /* U+03C0 */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - /* U+03C8 */ 0x03C8, 0x03C9, 0x03B9, 0x03C5, 0x03BF, 0x03C5, 0x03C9, 0x03CF, - /* U+03D0 */ 0x03B2, 0x03B8, 0x03A5, 0x03D2, 0x03D2, 0x03C6, 0x03C0, 0x03D7, - /* U+03D8 */ 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, - /* U+03E0 */ 0x03E0, 0x03E1, 0x03E2, 0x03E3, 0x03E4, 0x03E5, 0x03E6, 0x03E7, - /* U+03E8 */ 0x03E8, 0x03E9, 0x03EA, 0x03EB, 0x03EC, 0x03ED, 0x03EE, 0x03EF, - /* U+03F0 */ 0x03BA, 0x03C1, 0x03C2, 0x03F3, 0x0398, 0x03B5, 0x03F6, 0x03F7, - /* U+03F8 */ 0x03F8, 0x03A3, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, - /* U+0400 */ 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406, - /* U+0408 */ 0x0408, 0x0409, 0x040A, 0x040B, 0x041A, 0x0418, 0x0423, 0x040F, - /* U+0410 */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - /* U+0418 */ 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - // U+0419: Manually changed from 0418 to 0419 - /* U+0420 */ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - /* U+0428 */ 0x0428, 0x0429, 0x042C, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - // U+042A: Manually changed from 042A to 042C - /* U+0430 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - /* U+0438 */ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - // U+0439: Manually changed from 0438 to 0439 - /* U+0440 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - /* U+0448 */ 0x0448, 0x0449, 0x044C, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - // U+044A: Manually changed from 044A to 044C - /* U+0450 */ 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456, - /* U+0458 */ 0x0458, 0x0459, 0x045A, 0x045B, 0x043A, 0x0438, 0x0443, 0x045F, - /* U+0460 */ 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467, - /* U+0468 */ 0x0468, 0x0469, 0x046A, 0x046B, 0x046C, 0x046D, 0x046E, 0x046F, - /* U+0470 */ 0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0474, 0x0475, - /* U+0478 */ 0x0478, 0x0479, 0x047A, 0x047B, 0x047C, 0x047D, 0x047E, 0x047F, - /* U+0480 */ 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, - /* U+0488 */ 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F, - /* U+0490 */ 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, - /* U+0498 */ 0x0498, 0x0499, 0x049A, 0x049B, 0x049C, 0x049D, 0x049E, 0x049F, - /* U+04A0 */ 0x04A0, 0x04A1, 0x04A2, 0x04A3, 0x04A4, 0x04A5, 0x04A6, 0x04A7, - /* U+04A8 */ 0x04A8, 0x04A9, 0x04AA, 0x04AB, 0x04AC, 0x04AD, 0x04AE, 0x04AF, - /* U+04B0 */ 0x04B0, 0x04B1, 0x04B2, 0x04B3, 0x04B4, 0x04B5, 0x04B6, 0x04B7, - /* U+04B8 */ 0x04B8, 0x04B9, 0x04BA, 0x04BB, 0x04BC, 0x04BD, 0x04BE, 0x04BF, - /* U+04C0 */ 0x04C0, 0x0416, 0x0436, 0x04C3, 0x04C4, 0x04C5, 0x04C6, 0x04C7, - /* U+04C8 */ 0x04C8, 0x04C9, 0x04CA, 0x04CB, 0x04CC, 0x04CD, 0x04CE, 0x04CF, - /* U+04D0 */ 0x0410, 0x0430, 0x0410, 0x0430, 0x04D4, 0x04D5, 0x0415, 0x0435, - /* U+04D8 */ 0x04D8, 0x04D9, 0x04D8, 0x04D9, 0x0416, 0x0436, 0x0417, 0x0437, - /* U+04E0 */ 0x04E0, 0x04E1, 0x0418, 0x0438, 0x0418, 0x0438, 0x041E, 0x043E, - /* U+04E8 */ 0x04E8, 0x04E9, 0x04E8, 0x04E9, 0x042D, 0x044D, 0x0423, 0x0443, - /* U+04F0 */ 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0x04F6, 0x04F7, - /* U+04F8 */ 0x042B, 0x044B, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, - }; -} 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..955b83556 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(); @@ -725,8 +722,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen LatinImeLogger.commit(); LatinImeLogger.onDestroy(); if (mInputUpdater != null) { - mInputUpdater.onDestroy(); - mInputUpdater = null; + mInputUpdater.quitLooper(); } super.onDestroy(); } @@ -761,8 +757,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); } @@ -811,6 +808,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen super.onStartInputView(editorInfo, restarting); mRichImm.clearSubtypeCaches(); final KeyboardSwitcher switcher = mKeyboardSwitcher; + switcher.updateKeyboardTheme(); final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView(); // If we are starting input in a different text field from before, we'll have to reload // settings, so currentSettingsValues can't be final. @@ -907,9 +905,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // refresh later. final boolean canReachInputConnection; if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(editorInfo.initialSelStart, - false /* shouldFinishComposition */)) { + editorInfo.initialSelEnd, false /* shouldFinishComposition */)) { // We try resetting the caches up to 5 times before giving up. mHandler.postResetCaches(isDifferentTextField, 5 /* remainingTries */); + // mLastSelection{Start,End} are reset later in this method, don't need to do it here canReachInputConnection = false; } else { if (isDifferentTextField) { @@ -989,10 +988,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (textLength > mLastSelectionStart || (textLength < Constants.EDITOR_CONTENTS_CACHE_SIZE && mLastSelectionStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { + // It should not be possible to have only one of those variables be + // NOT_A_CURSOR_POSITION, so if they are equal, either the selection is zero-sized + // (simple cursor, no selection) or there is no cursor/we don't know its pos + final boolean wasEqual = mLastSelectionStart == mLastSelectionEnd; mLastSelectionStart = textLength; // We can't figure out the value of mLastSelectionEnd :( - // But at least if it's smaller than mLastSelectionStart something is wrong - if (mLastSelectionStart > mLastSelectionEnd) { + // But at least if it's smaller than mLastSelectionStart something is wrong, + // and if they used to be equal we also don't want to make it look like there is a + // selection. + if (wasEqual || mLastSelectionStart > mLastSelectionEnd) { mLastSelectionEnd = mLastSelectionStart; } } @@ -1081,16 +1086,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 +1107,8 @@ 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, + oldSelEnd, newSelEnd)) { // 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 @@ -1142,13 +1134,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Another option would be to send suggestions each time we set the composing // text, but that is probably too expensive to do, so we decided to leave things // as is. - resetEntireInputState(newSelStart); + resetEntireInputState(newSelStart, newSelEnd); } else { - // resetEntireInputState calls resetCachesUponCursorMove, but with the second - // argument as true. But in all cases where we don't reset the entire input state, - // we still want to tell the rich input connection about the new cursor position so - // that it can update its caches. - mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, + // resetEntireInputState calls resetCachesUponCursorMove, but forcing the + // composition to end. But in all cases where we don't reset the entire input + // state, we still want to tell the rich input connection about the new cursor + // position so that it can update its caches. + mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, newSelEnd, false /* shouldFinishComposition */); } @@ -1161,7 +1153,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 +1338,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 @@ -1373,7 +1363,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // This will reset the whole input state to the starting state. It will clear // the composing word, reset the last composed word, tell the inputconnection about it. - private void resetEntireInputState(final int newCursorPosition) { + private void resetEntireInputState(final int newSelStart, final int newSelEnd) { final boolean shouldFinishComposition = mWordComposer.isComposingWord(); resetComposingState(true /* alsoResetLastComposedWord */); final SettingsValues settingsValues = mSettings.getCurrent(); @@ -1382,14 +1372,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } else { setSuggestedWords(settingsValues.mSuggestPuncList, false); } - mConnection.resetCachesUponCursorMoveAndReturnSuccess(newCursorPosition, + mConnection.resetCachesUponCursorMoveAndReturnSuccess(newSelStart, newSelEnd, shouldFinishComposition); } 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 +1427,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); @@ -1457,7 +1449,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private boolean maybeDoubleSpacePeriod() { final SettingsValues currentSettingsValues = mSettings.getCurrent(); - if (!currentSettingsValues.mCorrectionEnabled) return false; if (!currentSettingsValues.mUseDoubleSpacePeriod) return false; if (!mHandler.isAcceptingDoubleSpacePeriod()) return false; // We only do this when we see two spaces and an accepted code point before the cursor. @@ -1502,6 +1493,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; } @@ -1723,7 +1715,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the character at the current cursor position. - resetEntireInputState(mLastSelectionStart); + resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); } else { commitTyped(LastComposedWord.NOT_A_SEPARATOR); } @@ -1739,7 +1731,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } handleCharacter(primaryCode, keyX, keyY, spaceState); } - mExpectingUpdateSelection = true; return didAutoCorrect; } @@ -1792,7 +1783,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the batch input at the current cursor position. - resetEntireInputState(mLastSelectionStart); + resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); } else if (wordComposerSize <= 1) { // We auto-correct the previous (typed, not gestured) string iff it's one character // long. The reason for this is, even in the middle of gesture typing, you'll still @@ -1805,7 +1796,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) @@ -1816,13 +1806,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode()); } - private static final class InputUpdater implements Handler.Callback { + static final class InputUpdater implements Handler.Callback { private final Handler mHandler; private final LatinIME mLatinIme; private final Object mLock = new Object(); private boolean mInBatchInput; // synchronized using {@link #mLock}. - private InputUpdater(final LatinIME latinIme) { + InputUpdater(final LatinIME latinIme) { final HandlerThread handlerThread = new HandlerThread( InputUpdater.class.getSimpleName()); handlerThread.start(); @@ -1939,7 +1929,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen .sendToTarget(); } - private void onDestroy() { + void quitLooper() { mHandler.removeMessages(MSG_GET_SUGGESTED_WORDS); mHandler.removeMessages(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP); mHandler.getLooper().quit(); @@ -1996,8 +1986,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 +2008,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 +2061,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 @@ -2085,7 +2071,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can remove the character at the current cursor position. - resetEntireInputState(mLastSelectionStart); + resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); // When we exit this if-clause, mWordComposer.isComposingWord() will return false. } if (mWordComposer.isComposingWord()) { @@ -2168,10 +2154,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 +2202,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 +2218,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. @@ -2256,7 +2239,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the character at the current cursor position. - resetEntireInputState(mLastSelectionStart); + resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); isComposingWord = false; } // We want to find out whether to start composing a new word with this character. If so, @@ -2303,8 +2286,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 +2325,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); @@ -2368,7 +2351,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the separator at the current cursor position. - resetEntireInputState(mLastSelectionStart); + resetEntireInputState(mLastSelectionStart, mLastSelectionEnd); } if (mWordComposer.isComposingWord()) { // May have changed since we stored wasComposing if (currentSettings.mCorrectionEnabled) { @@ -2541,6 +2524,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 +2549,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 +2667,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 +2737,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) { @@ -2999,7 +2983,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen * @param remainingTries How many times we may try again before giving up. */ private void retryResetCaches(final boolean tryResumeSuggestions, final int remainingTries) { - if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(mLastSelectionStart, false)) { + if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(mLastSelectionStart, + mLastSelectionEnd, false)) { if (0 < remainingTries) { mHandler.postResetCaches(tryResumeSuggestions, remainingTries - 1); return; @@ -3026,8 +3011,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 +3212,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 +3222,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()); } @@ -3301,11 +3284,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final Printer p = new PrintWriterPrinter(fout); p.println("LatinIME state :"); + p.println(" VersionCode = " + ApplicationUtils.getVersionCode(this)); + p.println(" VersionName = " + ApplicationUtils.getVersionName(this)); final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); 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/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index c212f9c81..4a7f530f9 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -57,14 +57,19 @@ public final class RichInputConnection { private static final int INVALID_CURSOR_POSITION = -1; /** - * This variable contains an expected value for the cursor position. This is where the - * cursor may end up after all the keyboard-triggered updates have passed. We keep this to - * compare it to the actual cursor position to guess whether the move was caused by a - * keyboard command or not. - * It's not really the cursor position: the cursor may not be there yet, and it's also expected - * there be cases where it never actually comes to be there. + * This variable contains an expected value for the selection start position. This is where the + * cursor or selection start may end up after all the keyboard-triggered updates have passed. We + * keep this to compare it to the actual selection start to guess whether the move was caused by + * a keyboard command or not. + * It's not really the selection start position: the selection start may not be there yet, and + * in some cases, it may never arrive there. */ - private int mExpectedCursorPosition = INVALID_CURSOR_POSITION; // in chars, not code points + private int mExpectedSelStart = INVALID_CURSOR_POSITION; // in chars, not code points + /** + * The expected selection end. Only differs from mExpectedSelStart if a non-empty selection is + * expected. The same caveats as mExpectedSelStart apply. + */ + private int mExpectedSelEnd = INVALID_CURSOR_POSITION; // in chars, not code points /** * This contains the committed text immediately preceding the cursor and the composing * text if any. It is refreshed when the cursor moves by calling upon the TextView. @@ -103,16 +108,16 @@ public final class RichInputConnection { final String reference = (beforeCursor.length() <= actualLength) ? beforeCursor.toString() : beforeCursor.subSequence(beforeCursor.length() - actualLength, beforeCursor.length()).toString(); - if (et.selectionStart != mExpectedCursorPosition + if (et.selectionStart != mExpectedSelStart || !(reference.equals(internal.toString()))) { - final String context = "Expected cursor position = " + mExpectedCursorPosition - + "\nActual cursor position = " + et.selectionStart + final String context = "Expected selection start = " + mExpectedSelStart + + "\nActual selection start = " + et.selectionStart + "\nExpected text = " + internal.length() + " " + internal + "\nActual text = " + reference.length() + " " + reference; ((LatinIME)mParent).debugDumpStateAndCrashWithException(context); } else { Log.e(TAG, DebugLogUtils.getStackTrace(2)); - Log.e(TAG, "Exp <> Actual : " + mExpectedCursorPosition + " <> " + et.selectionStart); + Log.e(TAG, "Exp <> Actual : " + mExpectedSelStart + " <> " + et.selectionStart); } } @@ -150,16 +155,50 @@ public final class RichInputConnection { * data, so we empty the cache and note that we don't know the new cursor position, and we * return false so that the caller knows about this and can retry later. * - * @param newCursorPosition The new position of the cursor, as received from the system. - * @param shouldFinishComposition Whether we should finish the composition in progress. + * @param newSelStart the new position of the selection start, as received from the system. + * @param newSelEnd the new position of the selection end, as received from the system. + * @param shouldFinishComposition whether we should finish the composition in progress. * @return true if we were able to connect to the editor successfully, false otherwise. When * this method returns false, the caches could not be correctly refreshed so they were only * reset: the caller should try again later to return to normal operation. */ - public boolean resetCachesUponCursorMoveAndReturnSuccess(final int newCursorPosition, - final boolean shouldFinishComposition) { - mExpectedCursorPosition = newCursorPosition; + public boolean resetCachesUponCursorMoveAndReturnSuccess(final int newSelStart, + final int newSelEnd, final boolean shouldFinishComposition) { + mExpectedSelStart = newSelStart; + mExpectedSelEnd = newSelEnd; mComposingText.setLength(0); + final boolean didReloadTextSuccessfully = reloadTextCache(); + if (!didReloadTextSuccessfully) { + Log.d(TAG, "Will try to retrieve text later."); + return false; + } + final int lengthOfTextBeforeCursor = mCommittedTextBeforeComposingText.length(); + if (lengthOfTextBeforeCursor > newSelStart + || (lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE + && newSelStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { + // newSelStart and newSelEnd may be lying -- when rotating the device (probably a + // framework bug). If we have less chars than we asked for, then we know how many chars + // we have, and if we got more than newSelStart says, then we know it was lying. In both + // cases the length is more reliable. Note that we only have to check newSelStart (not + // newSelEnd) since if newSelEnd is wrong, the newSelStart will be wrong as well. + mExpectedSelStart = lengthOfTextBeforeCursor; + mExpectedSelEnd = lengthOfTextBeforeCursor; + } + if (null != mIC && shouldFinishComposition) { + mIC.finishComposingText(); + if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { + ResearchLogger.richInputConnection_finishComposingText(); + } + } + return true; + } + + /** + * Reload the cached text from the InputConnection. + * + * @return true if successful + */ + private boolean reloadTextCache() { mCommittedTextBeforeComposingText.setLength(0); mIC = mParent.getCurrentInputConnection(); // Call upon the inputconnection directly since our own method is using the cache, and @@ -169,27 +208,12 @@ public final class RichInputConnection { if (null == textBeforeCursor) { // For some reason the app thinks we are not connected to it. This looks like a // framework bug... Fall back to ground state and return false. - mExpectedCursorPosition = INVALID_CURSOR_POSITION; - Log.e(TAG, "Unable to connect to the editor to retrieve text... will retry later"); + mExpectedSelStart = INVALID_CURSOR_POSITION; + mExpectedSelEnd = INVALID_CURSOR_POSITION; + Log.e(TAG, "Unable to connect to the editor to retrieve text."); return false; } mCommittedTextBeforeComposingText.append(textBeforeCursor); - final int lengthOfTextBeforeCursor = textBeforeCursor.length(); - if (lengthOfTextBeforeCursor > newCursorPosition - || (lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE - && newCursorPosition < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { - // newCursorPosition may be lying -- when rotating the device (probably a framework - // bug). If we have less chars than we asked for, then we know how many chars we have, - // and if we got more than newCursorPosition says, then we know it was lying. In both - // cases the length is more reliable - mExpectedCursorPosition = lengthOfTextBeforeCursor; - } - if (null != mIC && shouldFinishComposition) { - mIC.finishComposingText(); - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.richInputConnection_finishComposingText(); - } - } return true; } @@ -218,7 +242,7 @@ public final class RichInputConnection { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); mCommittedTextBeforeComposingText.append(text); - mExpectedCursorPosition += text.length() - mComposingText.length(); + mExpectedSelStart += text.length() - mComposingText.length(); mComposingText.setLength(0); if (null != mIC) { mIC.commitText(text, i); @@ -231,7 +255,7 @@ public final class RichInputConnection { } public boolean canDeleteCharacters() { - return mExpectedCursorPosition > 0; + return mExpectedSelStart > 0; } /** @@ -268,11 +292,10 @@ public final class RichInputConnection { // heavy pressing of delete, for example DEFAULT_TEXT_CACHE_SIZE - 5 times or so. // getCapsMode should be updated to be able to return a "not enough info" result so that // we can get more context only when needed. - if (TextUtils.isEmpty(mCommittedTextBeforeComposingText) && 0 != mExpectedCursorPosition) { - final CharSequence textBeforeCursor = getTextBeforeCursor( - Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); - if (!TextUtils.isEmpty(textBeforeCursor)) { - mCommittedTextBeforeComposingText.append(textBeforeCursor); + if (TextUtils.isEmpty(mCommittedTextBeforeComposingText) && 0 != mExpectedSelStart) { + if (!reloadTextCache()) { + Log.w(TAG, "Unable to connect to the editor. " + + "Setting caps mode without knowing text."); } } // This never calls InputConnection#getCapsMode - in fact, it's a static method that @@ -292,7 +315,11 @@ public final class RichInputConnection { mCommittedTextBeforeComposingText.length() + mComposingText.length(); // If we have enough characters to satisfy the request, or if we have all characters in // the text field, then we can return the cached version right away. - if (cachedLength >= n || cachedLength >= mExpectedCursorPosition) { + // However, if we don't have an expected cursor position, then we should always + // go fetch the cache again (as it happens, INVALID_CURSOR_POSITION < 0, so we need to + // test for this explicitly) + if (INVALID_CURSOR_POSITION != mExpectedSelStart + && (cachedLength >= n || cachedLength >= mExpectedSelStart)) { final StringBuilder s = new StringBuilder(mCommittedTextBeforeComposingText); // We call #toString() here to create a temporary object. // In some situations, this method is called on a worker thread, and it's possible @@ -332,10 +359,14 @@ public final class RichInputConnection { + remainingChars, 0); mCommittedTextBeforeComposingText.setLength(len); } - if (mExpectedCursorPosition > beforeLength) { - mExpectedCursorPosition -= beforeLength; + if (mExpectedSelStart > beforeLength) { + mExpectedSelStart -= beforeLength; + mExpectedSelEnd -= beforeLength; } else { - mExpectedCursorPosition = 0; + // There are fewer characters before the cursor in the buffer than we are being asked to + // delete. Only delete what is there. + mExpectedSelStart = 0; + mExpectedSelEnd -= mExpectedSelStart; } if (null != mIC) { mIC.deleteSurroundingText(beforeLength, afterLength); @@ -369,7 +400,8 @@ public final class RichInputConnection { switch (keyEvent.getKeyCode()) { case KeyEvent.KEYCODE_ENTER: mCommittedTextBeforeComposingText.append("\n"); - mExpectedCursorPosition += 1; + mExpectedSelStart += 1; + mExpectedSelEnd = mExpectedSelStart; break; case KeyEvent.KEYCODE_DEL: if (0 == mComposingText.length()) { @@ -381,18 +413,24 @@ public final class RichInputConnection { } else { mComposingText.delete(mComposingText.length() - 1, mComposingText.length()); } - if (mExpectedCursorPosition > 0) mExpectedCursorPosition -= 1; + if (mExpectedSelStart > 0 && mExpectedSelStart == mExpectedSelEnd) { + // TODO: Handle surrogate pairs. + mExpectedSelStart -= 1; + } + mExpectedSelEnd = mExpectedSelStart; break; case KeyEvent.KEYCODE_UNKNOWN: if (null != keyEvent.getCharacters()) { mCommittedTextBeforeComposingText.append(keyEvent.getCharacters()); - mExpectedCursorPosition += keyEvent.getCharacters().length(); + mExpectedSelStart += keyEvent.getCharacters().length(); + mExpectedSelEnd = mExpectedSelStart; } break; default: final String text = new String(new int[] { keyEvent.getUnicodeChar() }, 0, 1); mCommittedTextBeforeComposingText.append(text); - mExpectedCursorPosition += text.length(); + mExpectedSelStart += text.length(); + mExpectedSelEnd = mExpectedSelStart; break; } } @@ -426,10 +464,12 @@ public final class RichInputConnection { public void setComposingText(final CharSequence text, final int newCursorPosition) { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); - mExpectedCursorPosition += text.length() - mComposingText.length(); + mExpectedSelStart += text.length() - mComposingText.length(); + mExpectedSelEnd = mExpectedSelStart; mComposingText.setLength(0); mComposingText.append(text); - // TODO: support values of i != 1. At this time, this is never called with i != 1. + // TODO: support values of newCursorPosition != 1. At this time, this is never called with + // newCursorPosition != 1. if (null != mIC) { mIC.setComposingText(text, newCursorPosition); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { @@ -439,19 +479,30 @@ public final class RichInputConnection { if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); } - public void setSelection(final int start, final int end) { + /** + * Set the selection of the text editor. + * + * Calls through to {@link InputConnection#setSelection(int, int)}. + * + * @param start the character index where the selection should start. + * @param end the character index where the selection should end. + * @return Returns true on success, false if the input connection is no longer valid either when + * setting the selection or when retrieving the text cache at that point. + */ + public boolean setSelection(final int start, final int end) { if (DEBUG_BATCH_NESTING) checkBatchEdit(); if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); + mExpectedSelStart = start; if (null != mIC) { - mIC.setSelection(start, end); + final boolean isIcValid = mIC.setSelection(start, end); + if (!isIcValid) { + return false; + } if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.richInputConnection_setSelection(start, end); } } - mExpectedCursorPosition = start; - mCommittedTextBeforeComposingText.setLength(0); - mCommittedTextBeforeComposingText.append( - getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0)); + return reloadTextCache(); } public void commitCorrection(final CorrectionInfo correctionInfo) { @@ -472,7 +523,7 @@ public final class RichInputConnection { // text should never be null, but just in case, it's better to insert nothing than to crash if (null == text) text = ""; mCommittedTextBeforeComposingText.append(text); - mExpectedCursorPosition += text.length() - mComposingText.length(); + mExpectedSelStart += text.length() - mComposingText.length(); mComposingText.setLength(0); if (null != mIC) { mIC.commitCompletion(completionInfo); @@ -754,20 +805,30 @@ public final class RichInputConnection { * this update and not the ones in-between. This is almost impossible to achieve even trying * very very hard. * - * @param oldSelStart The value of the old cursor position in the update. - * @param newSelStart The value of the new cursor position in the update. + * @param oldSelStart The value of the old selection in the update. + * @param newSelStart The value of the new selection in the update. + * @param oldSelEnd The value of the old selection end in the update. + * @param newSelEnd The value of the new selection end in the update. * @return whether this is a belated expected update or not. */ - public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart) { - // If this is an update that arrives at our expected position, it's a belated update. - if (newSelStart == mExpectedCursorPosition) return true; - // If this is an update that moves the cursor from our expected position, it must be - // an explicit move. - if (oldSelStart == mExpectedCursorPosition) return false; - // The following returns true if newSelStart is between oldSelStart and - // mCurrentCursorPosition. We assume that if the updated position is between the old - // position and the expected position, then it must be a belated update. - return (newSelStart - oldSelStart) * (mExpectedCursorPosition - newSelStart) >= 0; + public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart, + final int oldSelEnd, final int newSelEnd) { + // This update is "belated" if we are expecting it. That is, mExpectedSelStart and + // mExpectedSelEnd match the new values that the TextView is updating TO. + if (mExpectedSelStart == newSelStart && mExpectedSelEnd == newSelEnd) return true; + // This update is not belated if mExpectedSelStart and mExpeectedSelend match the old + // values, and one of newSelStart or newSelEnd is updated to a different value. In this + // case, there is likely something other than the IME that has moved the selection endpoint + // to the new value. + if (mExpectedSelStart == oldSelStart && mExpectedSelEnd == oldSelEnd + && (oldSelStart != newSelStart || oldSelEnd != newSelEnd)) return false; + // If nether of the above two cases holds, then the system may be having trouble keeping up + // with updates. If 1) the selection is a cursor, 2) newSelStart is between oldSelStart + // and mExpectedSelStart, and 3) newSelEnd is between oldSelEnd and mExpectedSelEnd, then + // assume a belated update. + return (newSelStart == newSelEnd) + && (newSelStart - oldSelStart) * (mExpectedSelStart - newSelStart) >= 0 + && (newSelEnd - oldSelEnd) * (mExpectedSelEnd - newSelEnd) >= 0; } /** 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..c0dad3db2 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 @@ -690,6 +711,13 @@ public class BinaryDictEncoderUtils { + word + " is " + unigramFrequency); bigramFrequency = unigramFrequency; } + bigramFlags += getBigramFrequencyDiff(unigramFrequency, bigramFrequency) + & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY; + return bigramFlags; + } + + public static int getBigramFrequencyDiff(final int unigramFrequency, + final int bigramFrequency) { // We compute the difference between 255 (which means probability = 1) and the // unigram score. We split this into a number of discrete steps. // Now, the steps are numbered 0~15; 0 represents an increase of 1 step while 15 @@ -723,9 +751,7 @@ public class BinaryDictEncoderUtils { // include this bigram in the dictionary. For now, register as 0, and live with the // small over-estimation that we get in this case. TODO: actually remove this bigram // if discretizedFrequency < 0. - final int finalBigramFrequency = discretizedFrequency > 0 ? discretizedFrequency : 0; - bigramFlags += finalBigramFrequency & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY; - return bigramFlags; + return discretizedFrequency > 0 ? discretizedFrequency : 0; } /** 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..5aee135ad 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. @@ -261,8 +264,9 @@ public final class FormatSpec { static final int PTNODE_SHORTCUT_LIST_SIZE_SIZE = 2; // These values are used only by version 4 or later. - static final String TRIE_FILE_EXTENSION = ".trie"; + public 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/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index 1de15a333..e7a25d216 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -46,6 +46,7 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB private static final String TAG = DecayingExpandableBinaryDictionaryBase.class.getSimpleName(); public static final boolean DBG_SAVE_RESTORE = false; private static final boolean DBG_STRESS_TEST = false; + private static final boolean DBG_DUMP_ON_CLOSE = false; private static final boolean PROFILE_SAVE_RESTORE = LatinImeLogger.sDBG; /** Any pair being typed or picked */ @@ -75,15 +76,14 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB mFileName = fileName; mPrefs = sp; if (mLocale != null && mLocale.length() > 1) { - asyncLoadDictionaryToMemory(); reloadDictionaryIfRequired(); } } @Override public void close() { - if (!ExpandableBinaryDictionary.ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) { - closeBinaryDictionary(); + if (DBG_DUMP_ON_CLOSE) { + dumpAllWordsForDebug(); } // Flush pending writes. // TODO: Remove after this class become to use a dynamic binary dictionary. @@ -126,9 +126,8 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB (word0 != null && word0.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH)) { return; } - final int frequency = ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ? - (isValid ? FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS) : - FREQUENCY_FOR_TYPED; + final int frequency = isValid ? + FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS; addWordDynamically(word1, null /* shortcutTarget */, frequency, 0 /* shortcutFreq */, false /* isNotAWord */); // Do not insert a word as a bigram of itself @@ -222,6 +221,55 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB } @UsedForTesting + public void dumpAllWordsForDebug() { + runAfterGcForDebug(new Runnable() { + @Override + public void run() { + dumpAllWordsForDebugLocked(); + } + }); + } + + private void dumpAllWordsForDebugLocked() { + Log.d(TAG, "dumpAllWordsForDebug started."); + final OnAddWordListener listener = new OnAddWordListener() { + @Override + public void setUnigram(final String word, final String shortcutTarget, + final int frequency, final int shortcutFreq) { + Log.d(TAG, "load unigram: " + word + "," + frequency); + } + + @Override + public void setBigram(final String word0, final String word1, final int frequency) { + if (word0.length() < Constants.DICTIONARY_MAX_WORD_LENGTH + && word1.length() < Constants.DICTIONARY_MAX_WORD_LENGTH) { + Log.d(TAG, "load bigram: " + word0 + "," + word1 + "," + frequency); + } else { + Log.d(TAG, "Skip inserting a too long bigram: " + word0 + "," + word1 + "," + + frequency); + } + } + }; + + // Load the dictionary from binary file + final File dictFile = new File(mContext.getFilesDir(), mFileName); + final DictDecoder dictDecoder = FormatSpec.getDictDecoder(dictFile, + DictDecoder.USE_BYTEARRAY); + if (dictDecoder == null) { + // This is an expected condition: we don't have a user history dictionary for this + // language yet. It will be created sometime later. + return; + } + + try { + dictDecoder.openDictBuffer(); + UserHistoryDictIOUtils.readDictionaryBinary(dictDecoder, listener); + } catch (IOException e) { + Log.d(TAG, "IOException on opening a bytebuffer", e); + } + } + + @UsedForTesting public void clearAndFlushDictionary() { // Clear the node structure on memory clear(); diff --git a/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java b/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java deleted file mode 100644 index 6f152bb91..000000000 --- a/java/src/com/android/inputmethod/latin/personalization/DynamicPersonalizationDictionaryWriter.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin.personalization; - -import android.content.Context; - -import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.compat.ActivityManagerCompatUtils; -import com.android.inputmethod.keyboard.ProximityInfo; -import com.android.inputmethod.latin.AbstractDictionaryWriter; -import com.android.inputmethod.latin.ExpandableDictionary; -import com.android.inputmethod.latin.WordComposer; -import com.android.inputmethod.latin.ExpandableDictionary.NextWord; -import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; -import com.android.inputmethod.latin.makedict.DictEncoder; -import com.android.inputmethod.latin.makedict.FormatSpec; -import com.android.inputmethod.latin.makedict.UnsupportedFormatException; -import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils; -import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.BigramDictionaryInterface; -import com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils; -import com.android.inputmethod.latin.utils.UserHistoryForgettingCurveUtils.ForgettingCurveParams; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Map; - -// Currently this class is used to implement dynamic prodiction dictionary. -// TODO: Move to native code. -public class DynamicPersonalizationDictionaryWriter extends AbstractDictionaryWriter { - private static final String TAG = DynamicPersonalizationDictionaryWriter.class.getSimpleName(); - /** Maximum number of pairs. Pruning will start when databases goes above this number. */ - public static final int DEFAULT_MAX_HISTORY_BIGRAMS = 10000; - public static final int LOW_MEMORY_MAX_HISTORY_BIGRAMS = 2000; - - /** Any pair being typed or picked */ - private static final int FREQUENCY_FOR_TYPED = 2; - - private static final int BINARY_DICT_VERSION = 3; - private static final FormatSpec.FormatOptions FORMAT_OPTIONS = - new FormatSpec.FormatOptions(BINARY_DICT_VERSION, true /* supportsDynamicUpdate */); - - private final UserHistoryDictionaryBigramList mBigramList = - new UserHistoryDictionaryBigramList(); - private final ExpandableDictionary mExpandableDictionary; - private final int mMaxHistoryBigrams; - - public DynamicPersonalizationDictionaryWriter(final Context context, final String dictType) { - super(context, dictType); - mExpandableDictionary = new ExpandableDictionary(dictType); - final boolean isLowRamDevice = ActivityManagerCompatUtils.isLowRamDevice(context); - mMaxHistoryBigrams = isLowRamDevice ? - LOW_MEMORY_MAX_HISTORY_BIGRAMS : DEFAULT_MAX_HISTORY_BIGRAMS; - } - - @Override - public void clear() { - mBigramList.evictAll(); - mExpandableDictionary.clearDictionary(); - } - - /** - * Adds a word unigram to the fusion dictionary. Call updateBinaryDictionary when all changes - * are done to update the binary dictionary. - * @param word The word to add. - * @param shortcutTarget A shortcut target for this word, or null if none. - * @param frequency The frequency for this unigram. - * @param shortcutFreq The frequency of the shortcut (0~15, with 15 = whitelist). Ignored - * if shortcutTarget is null. - * @param isNotAWord true if this is not a word, i.e. shortcut only. - */ - @Override - public void addUnigramWord(final String word, final String shortcutTarget, final int frequency, - final int shortcutFreq, final boolean isNotAWord) { - if (mBigramList.size() > mMaxHistoryBigrams * 2) { - // Too many entries: just stop adding new vocabulary and wait next refresh. - return; - } - mExpandableDictionary.addWord(word, shortcutTarget, frequency, shortcutFreq); - mBigramList.addBigram(null, word, (byte)frequency); - } - - @Override - public void addBigramWords(final String word0, final String word1, final int frequency, - final boolean isValid, final long lastModifiedTime) { - if (mBigramList.size() > mMaxHistoryBigrams * 2) { - // Too many entries: just stop adding new vocabulary and wait next refresh. - return; - } - if (lastModifiedTime > 0) { - mExpandableDictionary.setBigramAndGetFrequency(word0, word1, - new ForgettingCurveParams(frequency, System.currentTimeMillis(), - lastModifiedTime)); - mBigramList.addBigram(word0, word1, (byte)frequency); - } else { - mExpandableDictionary.setBigramAndGetFrequency(word0, word1, - new ForgettingCurveParams(isValid)); - mBigramList.addBigram(word0, word1, (byte)frequency); - } - } - - @Override - public void removeBigramWords(final String word0, final String word1) { - if (mBigramList.removeBigram(word0, word1)) { - mExpandableDictionary.removeBigram(word0, word1); - } - } - - @Override - protected void writeDictionary(final DictEncoder dictEncoder, - final Map<String, String> attributeMap) throws IOException, UnsupportedFormatException { - UserHistoryDictIOUtils.writeDictionary(dictEncoder, - new FrequencyProvider(mBigramList, mExpandableDictionary, mMaxHistoryBigrams), - mBigramList, FORMAT_OPTIONS); - } - - private static class FrequencyProvider implements BigramDictionaryInterface { - private final UserHistoryDictionaryBigramList mBigramList; - private final ExpandableDictionary mExpandableDictionary; - private final int mMaxHistoryBigrams; - - public FrequencyProvider(final UserHistoryDictionaryBigramList bigramList, - final ExpandableDictionary expandableDictionary, final int maxHistoryBigrams) { - mBigramList = bigramList; - mExpandableDictionary = expandableDictionary; - mMaxHistoryBigrams = maxHistoryBigrams; - } - - @Override - public int getFrequency(final String word0, final String word1) { - final int freq; - if (word0 == null) { // unigram - freq = FREQUENCY_FOR_TYPED; - } else { // bigram - final NextWord nw = mExpandableDictionary.getBigramWord(word0, word1); - if (nw != null) { - final ForgettingCurveParams forgettingCurveParams = nw.getFcParams(); - final byte prevFc = mBigramList.getBigrams(word0).get(word1); - final byte fc = forgettingCurveParams.getFc(); - final boolean isValid = forgettingCurveParams.isValid(); - if (prevFc > 0 && prevFc == fc) { - freq = fc & 0xFF; - } else if (UserHistoryForgettingCurveUtils. - needsToSave(fc, isValid, mBigramList.size() <= mMaxHistoryBigrams)) { - freq = fc & 0xFF; - } else { - // Delete this entry - freq = -1; - } - } else { - // Delete this entry - freq = -1; - } - } - return freq; - } - } - - @Override - public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, - final String prevWord, final ProximityInfo proximityInfo, - boolean blockOffensiveWords, final int[] additionalFeaturesOptions) { - return mExpandableDictionary.getSuggestions(composer, prevWord, proximityInfo, - blockOffensiveWords, additionalFeaturesOptions); - } - - @Override - public boolean isValidWord(final String word) { - return mExpandableDictionary.isValidWord(word); - } - - @UsedForTesting - public boolean isInBigramListForTests(final String word) { - // TODO: Use native method to determine whether the word is in dictionary or not - return mBigramList.containsKey(word) || mBigramList.getBigrams(null).containsKey(word); - } -} diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java index 1b592b565..da1fb73fe 100644 --- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java @@ -113,9 +113,7 @@ public final class DebugSettings extends PreferenceFragment mServiceNeedsRestart = true; } } else if (key.equals(PREF_FORCE_NON_DISTINCT_MULTITOUCH) - || key.equals(KeyboardSwitcher.PREF_KEYBOARD_LAYOUT)) { - mServiceNeedsRestart = true; - } else if (key.equals(PREF_USE_ONLY_PERSONALIZATION_DICTIONARY_FOR_DEBUG)) { + || key.equals(PREF_USE_ONLY_PERSONALIZATION_DICTIONARY_FOR_DEBUG)) { mServiceNeedsRestart = true; } } diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index acd47450b..0e1a33a6c 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -75,7 +75,7 @@ public final class MoreSuggestions extends Keyboard { while (index < size) { final String word = suggestedWords.getWord(index); // TODO: Should take care of text x-scaling. - mWidths[index] = (int)(TypefaceUtils.getLabelWidth(word, paint) + padding); + mWidths[index] = (int)(TypefaceUtils.getStringWidth(word, paint) + padding); final int numColumn = index - rowStartIndex + 1; final int columnWidth = (maxWidth - mDividerWidth * (numColumn - 1)) / numColumn; diff --git a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java index d87f6f3c4..ef1d0f42c 100644 --- a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java @@ -17,21 +17,25 @@ package com.android.inputmethod.latin.utils; import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE; +import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.EMOJI_CAPABLE; import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE; import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; import android.os.Build; import android.text.TextUtils; +import android.util.Log; import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils; -import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import java.util.ArrayList; +import java.util.Arrays; public final class AdditionalSubtypeUtils { + private static final String TAG = AdditionalSubtypeUtils.class.getSimpleName(); + private static final InputMethodSubtype[] EMPTY_SUBTYPE_ARRAY = new InputMethodSubtype[0]; private AdditionalSubtypeUtils() { @@ -43,6 +47,11 @@ public final class AdditionalSubtypeUtils { } private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":"; + private static final int INDEX_OF_LOCALE = 0; + private static final int INDEX_OF_KEYBOARD_LAYOUT = 1; + private static final int INDEX_OF_EXTRA_VALUE = 2; + private static final int LENGTH_WITHOUT_EXTRA_VALUE = (INDEX_OF_KEYBOARD_LAYOUT + 1); + private static final int LENGTH_WITH_EXTRA_VALUE = (INDEX_OF_EXTRA_VALUE + 1); private static final String PREF_SUBTYPE_SEPARATOR = ";"; public static InputMethodSubtype createAdditionalSubtype(final String localeString, @@ -79,17 +88,6 @@ public final class AdditionalSubtypeUtils { : basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue; } - public static InputMethodSubtype createAdditionalSubtype(final String prefSubtype) { - final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR); - if (elems.length < 2 || elems.length > 3) { - throw new RuntimeException("Unknown additional subtype specified: " + prefSubtype); - } - final String localeString = elems[0]; - final String keyboardLayoutSetName = elems[1]; - final String extraValue = (elems.length == 3) ? elems[2] : null; - return createAdditionalSubtype(localeString, keyboardLayoutSetName, extraValue); - } - public static InputMethodSubtype[] createAdditionalSubtypesArray(final String prefSubtypes) { if (TextUtils.isEmpty(prefSubtypes)) { return EMPTY_SUBTYPE_ARRAY; @@ -98,7 +96,19 @@ public final class AdditionalSubtypeUtils { final ArrayList<InputMethodSubtype> subtypesList = CollectionUtils.newArrayList(prefSubtypeArray.length); for (final String prefSubtype : prefSubtypeArray) { - final InputMethodSubtype subtype = createAdditionalSubtype(prefSubtype); + final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR); + if (elems.length != LENGTH_WITHOUT_EXTRA_VALUE + && elems.length != LENGTH_WITH_EXTRA_VALUE) { + Log.w(TAG, "Unknown additional subtype specified: " + prefSubtype + " in " + + prefSubtypes); + continue; + } + final String localeString = elems[INDEX_OF_LOCALE]; + final String keyboardLayoutSetName = elems[INDEX_OF_KEYBOARD_LAYOUT]; + final String extraValue = (elems.length == LENGTH_WITH_EXTRA_VALUE) + ? elems[INDEX_OF_EXTRA_VALUE] : null; + final InputMethodSubtype subtype = createAdditionalSubtype( + localeString, keyboardLayoutSetName, extraValue); if (subtype.getNameResId() == SubtypeLocaleUtils.UNKNOWN_KEYBOARD_LAYOUT) { // Skip unknown keyboard layout subtype. This may happen when predefined keyboard // layout has been removed. @@ -137,31 +147,36 @@ public final class AdditionalSubtypeUtils { return sb.toString(); } - private static InputMethodSubtype buildInputMethodSubtype(int nameId, String localeString, - String layoutExtraValue, String additionalSubtypeExtraValue) { - // CAVEAT! If you want to change subtypeId after changing the extra values, - // you must change "getInputMethodSubtypeId". But it will remove the additional keyboard - // from the current users. So, you should be really careful to change it. - final int subtypeId = getInputMethodSubtypeId(nameId, localeString, layoutExtraValue, - additionalSubtypeExtraValue); + private static InputMethodSubtype buildInputMethodSubtype(final int nameId, + final String localeString, final String layoutExtraValue, + final String additionalSubtypeExtraValue) { + // To preserve additional subtype settings and user's selection across OS updates, subtype + // id shouldn't be changed. New attributes, such as emojiCapable, are carefully excluded + // from the calculation of subtype id. + final String compatibleExtraValue = StringUtils.joinCommaSplittableText( + layoutExtraValue, additionalSubtypeExtraValue); + final int compatibleSubtypeId = getInputMethodSubtypeId(localeString, compatibleExtraValue); final String extraValue; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - extraValue = layoutExtraValue + "," + additionalSubtypeExtraValue - + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE - + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE; + // Color Emoji is supported from KitKat. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + extraValue = StringUtils.appendToCommaSplittableTextIfNotExists( + EMOJI_CAPABLE, compatibleExtraValue); } else { - extraValue = layoutExtraValue + "," + additionalSubtypeExtraValue; + extraValue = compatibleExtraValue; } return InputMethodSubtypeCompatUtils.newInputMethodSubtype(nameId, R.drawable.ic_ime_switcher_dark, localeString, KEYBOARD_MODE, extraValue, - false, false, subtypeId); + false, false, compatibleSubtypeId); } - private static int getInputMethodSubtypeId(int nameId, String localeString, - String layoutExtraValue, String additionalSubtypeExtraValue) { - // TODO: Use InputMethodSubtypeBuilder once we use SDK version 19. - return (new InputMethodSubtype(nameId, R.drawable.ic_ime_switcher_dark, - localeString, KEYBOARD_MODE, layoutExtraValue + "," + additionalSubtypeExtraValue, - false, false)).hashCode(); + private static int getInputMethodSubtypeId(final String localeString, final String extraValue) { + // From the compatibility point of view, the calculation of subtype id has been copied from + // {@link InputMethodSubtype} of JellyBean MR2. + return Arrays.hashCode(new Object[] { + localeString, + KEYBOARD_MODE, + extraValue, + false /* isAuxiliary */, + false /* overrideImplicitlyEnabledSubtype */ }); } } diff --git a/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java b/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java index 08a2a8c5a..e521ec807 100644 --- a/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ApplicationUtils.java @@ -62,4 +62,22 @@ public final class ApplicationUtils { } return ""; } + + /** + * A utility method to get the application's PackageInfo.versionCode + * @return the application's PackageInfo.versionCode + */ + public static int getVersionCode(final Context context) { + try { + if (context == null) { + return 0; + } + final String packageName = context.getPackageName(); + final PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); + return info.versionCode; + } catch (final NameNotFoundException e) { + Log.e(TAG, "Could not find version info.", e); + } + return 0; + } } diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index a36548392..4cc89d0a7 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -39,6 +39,8 @@ public final class StringUtils { public static final int CAPITALIZE_FIRST = 1; // First only public static final int CAPITALIZE_ALL = 2; // All caps + private static final String EMPTY_STRING = ""; + private StringUtils() { // This utility class is not publicly instantiable. } @@ -80,6 +82,20 @@ public final class StringUtils { return containsInArray(text, extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT)); } + public static String joinCommaSplittableText(final String head, final String tail) { + if (TextUtils.isEmpty(head) && TextUtils.isEmpty(tail)) { + return EMPTY_STRING; + } + // Here either head or tail is not null. + if (TextUtils.isEmpty(head)) { + return tail; + } + if (TextUtils.isEmpty(tail)) { + return head; + } + return head + SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT + tail; + } + public static String appendToCommaSplittableTextIfNotExists(final String text, final String extraValues) { if (TextUtils.isEmpty(extraValues)) { @@ -94,7 +110,7 @@ public final class StringUtils { public static String removeFromCommaSplittableTextIfExists(final String text, final String extraValues) { if (TextUtils.isEmpty(extraValues)) { - return ""; + return EMPTY_STRING; } final String[] elements = extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT); if (!containsInArray(text, elements)) { @@ -380,7 +396,7 @@ public final class StringUtils { @UsedForTesting public static String byteArrayToHexString(byte[] bytes) { if (bytes == null || bytes.length == 0) { - return ""; + return EMPTY_STRING; } final StringBuilder sb = new StringBuilder(); for (byte b : bytes) { @@ -444,7 +460,7 @@ public final class StringUtils { public static String listToJsonStr(List<Object> list) { if (list == null || list.isEmpty()) { - return ""; + return EMPTY_STRING; } final StringWriter sw = new StringWriter(); final JsonWriter writer = new JsonWriter(sw); @@ -470,6 +486,6 @@ public final class StringUtils { } catch (IOException e) { } } - return ""; + return EMPTY_STRING; } } 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/latin/utils/TypefaceUtils.java b/java/src/com/android/inputmethod/latin/utils/TypefaceUtils.java index 47ea1ea75..087a7f255 100644 --- a/java/src/com/android/inputmethod/latin/utils/TypefaceUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/TypefaceUtils.java @@ -22,6 +22,9 @@ import android.graphics.Typeface; import android.util.SparseArray; public final class TypefaceUtils { + private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' }; + private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' }; + private TypefaceUtils() { // This utility class is not publicly instantiable. } @@ -31,7 +34,7 @@ public final class TypefaceUtils { // Working variable for the following method. private static final Rect sTextHeightBounds = new Rect(); - public static float getCharHeight(final char[] referenceChar, final Paint paint) { + private static float getCharHeight(final char[] referenceChar, final Paint paint) { final int key = getCharGeometryCacheKey(referenceChar[0], paint); synchronized (sTextHeightCache) { final Float cachedValue = sTextHeightCache.get(key); @@ -51,7 +54,7 @@ public final class TypefaceUtils { // Working variable for the following method. private static final Rect sTextWidthBounds = new Rect(); - public static float getCharWidth(final char[] referenceChar, final Paint paint) { + private static float getCharWidth(final char[] referenceChar, final Paint paint) { final int key = getCharGeometryCacheKey(referenceChar[0], paint); synchronized (sTextWidthCache) { final Float cachedValue = sTextWidthCache.get(key); @@ -66,11 +69,6 @@ public final class TypefaceUtils { } } - public static float getStringWidth(final String string, final Paint paint) { - paint.getTextBounds(string, 0, string.length(), sTextWidthBounds); - return sTextWidthBounds.width(); - } - private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) { final int labelSize = (int)paint.getTextSize(); final Typeface face = paint.getTypeface(); @@ -86,9 +84,25 @@ public final class TypefaceUtils { } } - public static float getLabelWidth(final String label, final Paint paint) { - final Rect textBounds = new Rect(); - paint.getTextBounds(label, 0, label.length(), textBounds); - return textBounds.width(); + public static float getReferenceCharHeight(final Paint paint) { + return getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint); + } + + public static float getReferenceCharWidth(final Paint paint) { + return getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint); + } + + public static float getReferenceDigitWidth(final Paint paint) { + return getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint); + } + + // Working variable for the following method. + private static final Rect sStringWidthBounds = new Rect(); + + public static float getStringWidth(final String string, final Paint paint) { + synchronized (sStringWidthBounds) { + paint.getTextBounds(string, 0, string.length(), sStringWidthBounds); + return sStringWidthBounds.width(); + } } } diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java index 635afe7cc..7b81e8be1 100644 --- a/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryDictIOUtils.java @@ -70,6 +70,7 @@ public final class UserHistoryDictIOUtils { /** * Writes dictionary to file. */ + @UsedForTesting public static void writeDictionary(final DictEncoder dictEncoder, final BigramDictionaryInterface dict, final UserHistoryDictionaryBigramList bigrams, final FormatOptions formatOptions) { diff --git a/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java b/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java index 1992b2f5d..677035ed6 100644 --- a/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/UserHistoryForgettingCurveUtils.java @@ -20,6 +20,9 @@ import android.util.Log; import java.util.concurrent.TimeUnit; +import com.android.inputmethod.annotations.UsedForTesting; + +@UsedForTesting public final class UserHistoryForgettingCurveUtils { private static final String TAG = UserHistoryForgettingCurveUtils.class.getSimpleName(); private static final boolean DEBUG = false; @@ -118,18 +121,22 @@ public final class UserHistoryForgettingCurveUtils { } } + @UsedForTesting /* package */ static int fcToElapsedTime(byte fc) { return fc & 0x0F; } + @UsedForTesting /* package */ static int fcToCount(byte fc) { return (fc >> 4) & 0x03; } + @UsedForTesting /* package */ static int fcToLevel(byte fc) { return (fc >> 6) & 0x03; } + @UsedForTesting private static int calcFreq(int elapsedTime, int count, int level) { if (level <= 0) { // Reserved words, just return -1 @@ -158,6 +165,7 @@ public final class UserHistoryForgettingCurveUtils { return calcFreq(elapsedTime, count, level); } + @UsedForTesting public static byte pushElapsedTime(byte fc) { int elapsedTime = fcToElapsedTime(fc); int count = fcToCount(fc); @@ -173,6 +181,7 @@ public final class UserHistoryForgettingCurveUtils { return calcFc(elapsedTime, count, level); } + @UsedForTesting public static byte pushCount(byte fc, boolean isValid) { final int elapsedTime = fcToElapsedTime(fc); int count = fcToCount(fc); 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..e770d9866 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 \ @@ -67,27 +68,45 @@ LATIN_IME_CORE_SRC_FILES := \ suggest/core/policy/weighting.cpp \ suggest/core/session/dic_traverse_session.cpp \ $(addprefix suggest/policyimpl/dictionary/, \ - bigram/bigram_list_read_write_utils.cpp \ - bigram/dynamic_bigram_list_policy.cpp \ 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/bigram/, \ + bigram_list_read_write_utils.cpp \ + dynamic_bigram_list_policy.cpp \ + ver4_bigram_list_policy.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_node_writer.cpp \ dynamic_patricia_trie_policy.cpp \ dynamic_patricia_trie_reading_helper.cpp \ dynamic_patricia_trie_reading_utils.cpp \ + dynamic_patricia_trie_updating_helper.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/, \ + content/bigram_dict_content.cpp \ + content/sparse_table_dict_content.cpp \ + ver4_dict_buffers.cpp \ + ver4_dict_constants.cpp \ + ver4_patricia_trie_node_reader.cpp \ + ver4_patricia_trie_node_writer.cpp \ + ver4_patricia_trie_policy.cpp \ + ver4_patricia_trie_reading_utils.cpp ) \ $(addprefix suggest/policyimpl/dictionary/utils/, \ buffer_with_extendable_buffer.cpp \ byte_array_utils.cpp \ dict_file_writing_utils.cpp \ + file_utils.cpp \ forgetting_curve_utils.cpp \ - format_utils.cpp) \ + format_utils.cpp \ + mmapped_buffer.cpp \ + sparse_table.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..c4383d754 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) { + 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/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp new file mode 100644 index 000000000..94d7f1061 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.cpp @@ -0,0 +1,142 @@ +/* + * 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/bigram/ver4_bigram_list_policy.h" + +#include "suggest/policyimpl/dictionary/bigram/bigram_list_read_write_utils.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" + +namespace latinime { + +void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const outProbability, + bool *const outHasNext, int *const bigramEntryPos) const { + int targetTerminalId = Ver4DictConstants::NOT_A_TERMINAL_ID; + mBigramDictContent->getBigramEntryAndAdvancePosition(outProbability, outHasNext, + &targetTerminalId, bigramEntryPos); + if (outBigramPos) { + // Lookup target PtNode position. + *outBigramPos = mTerminalPositionLookupTable->getTerminalPtNodePosition(targetTerminalId); + } +} + +bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId, + const int newProbability, bool *const outAddedNewEntry) { + if (outAddedNewEntry) { + *outAddedNewEntry = false; + } + const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId); + if (bigramListPos == NOT_A_DICT_POS) { + // Updating PtNode doesn't have a bigram list. + // Create new bigram list. + if (!mBigramDictContent->createNewBigramList(terminalId)) { + return false; + } + // Write an entry. + int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId); + if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(newProbability, + false /* hasNext */, newTargetTerminalId, &writingPos)) { + return false; + } + return true; + } + + const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos); + if (entryPosToUpdate != NOT_A_DICT_POS) { + // Overwrite existing entry. + int readingPos = entryPosToUpdate; + bool hasNext = false; + int probability = NOT_A_PROBABILITY; + int targetTerminalId = Ver4DictConstants::NOT_A_TERMINAL_ID; + mBigramDictContent->getBigramEntryAndAdvancePosition(&probability, &hasNext, + &targetTerminalId, &readingPos); + if (targetTerminalId == Ver4DictConstants::NOT_A_TERMINAL_ID && outAddedNewEntry) { + // Reuse invalid entry. + *outAddedNewEntry = true; + } + int writingPos = entryPosToUpdate; + return mBigramDictContent->writeBigramEntryAndAdvancePosition(newProbability, hasNext, + newTargetTerminalId, &writingPos); + } + + // Add new entry to the bigram list. + // Create new bigram list. + if (!mBigramDictContent->createNewBigramList(terminalId)) { + return false; + } + // Write new entry at a head position of the bigram list. + int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId); + if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(newProbability, + true /* hasNext */, newTargetTerminalId, &writingPos)) { + return false; + } + if (outAddedNewEntry) { + *outAddedNewEntry = true; + } + // Append existing entries by copying. + return mBigramDictContent->copyBigramList(bigramListPos, writingPos); +} + +bool Ver4BigramListPolicy::removeEntry(const int terminalId, const int targetTerminalId) { + const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId); + if (bigramListPos == NOT_A_DICT_POS) { + // Bigram list does't exist. + return false; + } + const int entryPosToUpdate = getEntryPosToUpdate(targetTerminalId, bigramListPos); + if (entryPosToUpdate == NOT_A_DICT_POS) { + // Bigram entry doesn't exist. + return false; + } + int readingPos = entryPosToUpdate; + bool hasNext = false; + int probability = NOT_A_PROBABILITY; + int originalTargetTerminalId = Ver4DictConstants::NOT_A_TERMINAL_ID; + mBigramDictContent->getBigramEntryAndAdvancePosition(&probability, &hasNext, + &originalTargetTerminalId, &readingPos); + if (targetTerminalId != originalTargetTerminalId) { + // Bigram entry doesn't exist. + return false; + } + int writingPos = entryPosToUpdate; + // Remove bigram entry by overwriting target terminal Id. + return mBigramDictContent->writeBigramEntryAndAdvancePosition(probability, hasNext, + Ver4DictConstants::NOT_A_TERMINAL_ID /* targetTerminalId */, &writingPos); +} + +int Ver4BigramListPolicy::getEntryPosToUpdate(const int targetTerminalIdToFind, + const int bigramListPos) const { + bool hasNext = true; + int invalidEntryPos = NOT_A_DICT_POS; + int readingPos = bigramListPos; + while(hasNext) { + const int entryPos = readingPos; + int targetTerminalId = Ver4DictConstants::NOT_A_TERMINAL_ID; + mBigramDictContent->getBigramEntryAndAdvancePosition(0 /* probability */, &hasNext, + &targetTerminalId, &readingPos); + if (targetTerminalId == targetTerminalIdToFind) { + // Entry with same target is found. + return entryPos; + } else if (targetTerminalId == Ver4DictConstants::NOT_A_TERMINAL_ID) { + // Invalid entry that can be reused is found. + invalidEntryPos = entryPos; + } + } + return invalidEntryPos; +} + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h new file mode 100644 index 000000000..b3fe13d7d --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LATINIME_VER4_BIGRAM_LIST_POLICY_H +#define LATINIME_VER4_BIGRAM_LIST_POLICY_H + +#include "defines.h" +#include "suggest/core/policy/dictionary_bigrams_structure_policy.h" + +namespace latinime { + +class BigramDictContent; +class TerminalPositionLookupTable; + +class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy { + public: + Ver4BigramListPolicy(BigramDictContent *const bigramDictContent, + const TerminalPositionLookupTable *const terminalPositionLookupTable) + : mBigramDictContent(bigramDictContent), + mTerminalPositionLookupTable(terminalPositionLookupTable) {} + + void getNextBigram(int *const outBigramPos, int *const outProbability, + bool *const outHasNext, int *const bigramEntryPos) const; + + void skipAllBigrams(int *const pos) const { + // Do nothing because we don't need to skip bigram lists in ver4 dictionaries. + } + + bool addNewEntry(const int terminalId, const int newTargetTerminalId, const int newProbability, + bool *const outAddedNewEntry); + + bool removeEntry(const int terminalId, const int targetTerminalId); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4BigramListPolicy); + + int getEntryPosToUpdate(const int targetTerminalIdToFind, const int bigramListPos) const; + + BigramDictContent *const mBigramDictContent; + const TerminalPositionLookupTable *const mTerminalPositionLookupTable; +}; +} // namespace latinime +#endif /* LATINIME_VER4_BIGRAM_LIST_POLICY_H */ 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/dynamic_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp deleted file mode 100644 index 052558bfc..000000000 --- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp +++ /dev/null @@ -1,558 +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_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/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" -#include "utils/hash_map_compat.h" - -namespace latinime { - -const int DynamicPatriciaTrieWritingHelper::CHILDREN_POSITION_FIELD_SIZE = 3; -// TODO: Make MAX_DICTIONARY_SIZE 8MB. -const size_t DynamicPatriciaTrieWritingHelper::MAX_DICTIONARY_SIZE = 2 * 1024 * 1024; - -bool DynamicPatriciaTrieWritingHelper::addUnigramWord( - DynamicPatriciaTrieReadingHelper *const readingHelper, - const int *const wordCodePoints, const int codePointCount, const int probability, - bool *const outAddedNewUnigram) { - int parentPos = NOT_A_DICT_POS; - while (!readingHelper->isEnd()) { - const int matchedCodePointCount = readingHelper->getPrevTotalCodePointCount(); - if (!readingHelper->isMatchedCodePoint(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(); - continue; - } - // Check following merged node code points. - const DynamicPatriciaTrieNodeReader *const nodeReader = readingHelper->getNodeReader(); - const int nodeCodePointCount = nodeReader->getCodePointCount(); - for (int j = 1; j < nodeCodePointCount; ++j) { - const int nextIndex = matchedCodePointCount + j; - if (nextIndex >= codePointCount || !readingHelper->isMatchedCodePoint(j, - wordCodePoints[matchedCodePointCount + j])) { - *outAddedNewUnigram = true; - return reallocatePtNodeAndAddNewPtNodes(nodeReader, - readingHelper->getMergedNodeCodePoints(), j, - getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, - probability), - wordCodePoints + matchedCodePointCount, - codePointCount - matchedCodePointCount); - } - } - // All characters are matched. - if (codePointCount == readingHelper->getTotalCodePointCount()) { - return setPtNodeProbability(nodeReader, probability, - readingHelper->getMergedNodeCodePoints(), outAddedNewUnigram); - } - if (!nodeReader->hasChildren()) { - *outAddedNewUnigram = true; - return createChildrenPtNodeArrayAndAChildPtNode(nodeReader, - getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability), - wordCodePoints + readingHelper->getTotalCodePointCount(), - codePointCount - readingHelper->getTotalCodePointCount()); - } - // Advance to the children nodes. - parentPos = nodeReader->getHeadPos(); - readingHelper->readChildNode(); - } - if (readingHelper->isError()) { - // The dictionary is invalid. - return false; - } - int pos = readingHelper->getPosOfLastForwardLinkField(); - *outAddedNewUnigram = true; - return createAndInsertNodeIntoPtNodeArray(parentPos, - wordCodePoints + readingHelper->getPrevTotalCodePointCount(), - codePointCount - readingHelper->getPrevTotalCodePointCount(), - getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability), &pos); -} - -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); - // Move node to add bigram entry. - const int newNodePos = mBuffer->getTailPosition(); - if (!markNodeAsMovedAndSetPosition(&nodeReader, 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)) { - return false; - } - nodeReader.fetchNodeInfoInBufferFromPtNodePos(newNodePos); - if (nodeReader.getBigramsPos() != NOT_A_DICT_POS) { - // Insert a new bigram entry into the existing bigram list. - int bigramListPos = nodeReader.getBigramsPos(); - return mBigramPolicy->addNewBigramEntryToBigramList(word1Pos, probability, &bigramListPos, - outAddedNewBigram); - } else { - // The PtNode doesn't have a bigram list. - *outAddedNewBigram = true; - // First, Write a bigram entry at the tail position of the PtNode. - if (!mBigramPolicy->writeNewBigramEntry(word1Pos, probability, &writingPos)) { - return false; - } - // 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); - writingPos = newNodePos; - // Write updated flags into the moved PtNode's flags field. - return DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags, - &writingPos); - } -} - -// 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) { - return false; - } - return mBigramPolicy->removeBigram(nodeReader.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 */); - const int extendedRegionSize = headerPolicy->getExtendedRegionSize() + - mBuffer->getUsedAdditionalBufferSize(); - if (!headerPolicy->writeHeaderToBuffer(&headerBuffer, false /* updatesLastUpdatedTime */, - false /* updatesLastDecayedTime */, unigramCount, bigramCount, extendedRegionSize)) { - return; - } - DictFileWritingUtils::flushAllHeaderAndBodyToFile(fileName, &headerBuffer, mBuffer); -} - -void DynamicPatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos, - const char *const fileName, const HeaderPolicy *const headerPolicy) { - BufferWithExtendableBuffer newDictBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */, - MAX_DICTIONARY_SIZE); - int unigramCount = 0; - int bigramCount = 0; - if (mNeedsToDecay) { - ForgettingCurveUtils::sTimeKeeper.setCurrentTime(); - } - if (!runGC(rootPtNodeArrayPos, headerPolicy, &newDictBuffer, &unigramCount, &bigramCount)) { - return; - } - BufferWithExtendableBuffer headerBuffer(0 /* originalBuffer */, 0 /* originalBufferSize */); - if (!headerPolicy->writeHeaderToBuffer(&headerBuffer, true /* updatesLastUpdatedTime */, - mNeedsToDecay, unigramCount, bigramCount, 0 /* extendedRegionSize */)) { - return; - } - DictFileWritingUtils::flushAllHeaderAndBodyToFile(fileName, &headerBuffer, &newDictBuffer); -} - -bool DynamicPatriciaTrieWritingHelper::markNodeAsDeleted( - const DynamicPatriciaTrieNodeReader *const nodeToUpdate) { - int pos = nodeToUpdate->getHeadPos(); - const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(pos); - const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer); - if (usesAdditionalBuffer) { - pos -= mBuffer->getOriginalBufferSize(); - } - // Read original flags - const PatriciaTrieReadingUtils::NodeFlags originalFlags = - PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos); - const PatriciaTrieReadingUtils::NodeFlags updatedFlags = - DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */, - true /* isDeleted */); - int writingPos = nodeToUpdate->getHeadPos(); - // Update flags. - return DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags, - &writingPos); -} - -bool DynamicPatriciaTrieWritingHelper::markNodeAsMovedAndSetPosition( - const DynamicPatriciaTrieNodeReader *const originalNode, const int movedPos, - const int bigramLinkedNodePos) { - int pos = originalNode->getHeadPos(); - const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(pos); - const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer); - if (usesAdditionalBuffer) { - pos -= mBuffer->getOriginalBufferSize(); - } - // Read original flags - const PatriciaTrieReadingUtils::NodeFlags originalFlags = - PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos); - const PatriciaTrieReadingUtils::NodeFlags updatedFlags = - DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */, - false /* isDeleted */); - int writingPos = originalNode->getHeadPos(); - // Update flags. - if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags, - &writingPos)) { - return false; - } - // Update moved position, which is stored in the parent offset field. - if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition( - mBuffer, movedPos, originalNode->getHeadPos(), &writingPos)) { - return false; - } - // Update bigram linked node position, which is stored in the children position field. - int childrenPosFieldPos = originalNode->getChildrenPosFieldPos(); - if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition( - mBuffer, bigramLinkedNodePos, &childrenPosFieldPos)) { - return false; - } - if (originalNode->hasChildren()) { - // Update children's parent position. - DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy); - const DynamicPatriciaTrieNodeReader *const nodeReader = readingHelper.getNodeReader(); - readingHelper.initWithPtNodeArrayPos(originalNode->getChildrenPos()); - while (!readingHelper.isEnd()) { - int parentOffsetFieldPos = nodeReader->getHeadPos() - + DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE; - if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition( - mBuffer, bigramLinkedNodePos, nodeReader->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(); - } - } - return true; -} - -// Write new PtNode at writingPos. -bool DynamicPatriciaTrieWritingHelper::writePtNodeWithFullInfoToBuffer( - BufferWithExtendableBuffer *const bufferToWrite, const bool isBlacklisted, - const bool isNotAWord, const int parentPos, const int *const codePoints, - const int codePointCount, const int probability, const int childrenPos, - const int originalBigramListPos, const int originalShortcutListPos, - int *const writingPos) { - const int nodePos = *writingPos; - // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the - // PtNode writing. - if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(bufferToWrite, - 0 /* nodeFlags */, writingPos)) { - return false; - } - // Calculate a parent offset and write the offset. - if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition(bufferToWrite, - parentPos, nodePos, writingPos)) { - return false; - } - // Write code points - if (!DynamicPatriciaTrieWritingUtils::writeCodePointsAndAdvancePosition(bufferToWrite, - codePoints, codePointCount, writingPos)) { - return false; - } - // Write probability when the probability is a valid probability, which means this node is - // terminal. - if (probability != NOT_A_PROBABILITY) { - if (!DynamicPatriciaTrieWritingUtils::writeProbabilityAndAdvancePosition(bufferToWrite, - probability, writingPos)) { - return false; - } - } - // Write children position - if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(bufferToWrite, - childrenPos, writingPos)) { - return false; - } - // Copy shortcut list when the originalShortcutListPos is valid dictionary position. - if (originalShortcutListPos != NOT_A_DICT_POS) { - int fromPos = originalShortcutListPos; - if (!mShortcutPolicy->copyAllShortcutsAndReturnIfSucceededOrNot(bufferToWrite, &fromPos, - writingPos)) { - return false; - } - } - // Copy bigram list when the originalBigramListPos is valid dictionary position. - int bigramCount = 0; - if (originalBigramListPos != NOT_A_DICT_POS) { - int fromPos = originalBigramListPos; - if (!mBigramPolicy->copyAllBigrams(bufferToWrite, &fromPos, writingPos, &bigramCount)) { - return false; - } - } - // Create node flags and write them. - PatriciaTrieReadingUtils::NodeFlags nodeFlags = - PatriciaTrieReadingUtils::createAndGetFlags(isBlacklisted, isNotAWord, - probability != NOT_A_PROBABILITY /* isTerminal */, - originalShortcutListPos != NOT_A_DICT_POS /* hasShortcutTargets */, - bigramCount > 0 /* hasBigrams */, codePointCount > 1 /* hasMultipleChars */, - CHILDREN_POSITION_FIELD_SIZE); - int flagsFieldPos = nodePos; - if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(bufferToWrite, nodeFlags, - &flagsFieldPos)) { - return false; - } - return true; -} - -bool DynamicPatriciaTrieWritingHelper::writePtNodeToBuffer( - BufferWithExtendableBuffer *const bufferToWrite, const int parentPos, - const int *const codePoints, const int codePointCount, const int probability, - int *const writingPos) { - return writePtNodeWithFullInfoToBuffer(bufferToWrite, false /* isBlacklisted */, - false /* isNotAWord */, parentPos, codePoints, codePointCount, probability, - NOT_A_DICT_POS /* childrenPos */, NOT_A_DICT_POS /* originalBigramsPos */, - NOT_A_DICT_POS /* originalShortcutPos */, writingPos); -} - -bool DynamicPatriciaTrieWritingHelper::writePtNodeToBufferByCopyingPtNodeInfo( - BufferWithExtendableBuffer *const bufferToWrite, - const DynamicPatriciaTrieNodeReader *const originalNode, 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); -} - -bool DynamicPatriciaTrieWritingHelper::createAndInsertNodeIntoPtNodeArray(const int parentPos, - const int *const nodeCodePoints, const int nodeCodePointCount, const int probability, - int *const forwardLinkFieldPos) { - const int newPtNodeArrayPos = mBuffer->getTailPosition(); - if (!DynamicPatriciaTrieWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer, - newPtNodeArrayPos, forwardLinkFieldPos)) { - return false; - } - return createNewPtNodeArrayWithAChildPtNode(parentPos, nodeCodePoints, nodeCodePointCount, - probability); -} - -bool DynamicPatriciaTrieWritingHelper::setPtNodeProbability( - const DynamicPatriciaTrieNodeReader *const originalPtNode, const int probability, - const int *const codePoints, bool *const outAddedNewUnigram) { - if (originalPtNode->isTerminal()) { - // Overwrites the probability. - *outAddedNewUnigram = false; - const int probabilityToWrite = getUpdatedProbability(originalPtNode->getProbability(), - probability); - int probabilityFieldPos = originalPtNode->getProbabilityFieldPos(); - if (!DynamicPatriciaTrieWritingUtils::writeProbabilityAndAdvancePosition(mBuffer, - probabilityToWrite, &probabilityFieldPos)) { - return false; - } - } else { - // Make the node terminal and write the probability. - *outAddedNewUnigram = true; - int movedPos = mBuffer->getTailPosition(); - if (!markNodeAsMovedAndSetPosition(originalPtNode, movedPos, movedPos)) { - return false; - } - if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, originalPtNode, - originalPtNode->getParentPos(), codePoints, originalPtNode->getCodePointCount(), - getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability), - &movedPos)) { - return false; - } - } - return true; -} - -bool DynamicPatriciaTrieWritingHelper::createChildrenPtNodeArrayAndAChildPtNode( - const DynamicPatriciaTrieNodeReader *const parentNode, const int probability, - const int *const codePoints, const int codePointCount) { - const int newPtNodeArrayPos = mBuffer->getTailPosition(); - int childrenPosFieldPos = parentNode->getChildrenPosFieldPos(); - if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBuffer, - newPtNodeArrayPos, &childrenPosFieldPos)) { - return false; - } - return createNewPtNodeArrayWithAChildPtNode(parentNode->getHeadPos(), codePoints, - codePointCount, probability); -} - -bool DynamicPatriciaTrieWritingHelper::createNewPtNodeArrayWithAChildPtNode( - const int parentPtNodePos, const int *const nodeCodePoints, const int nodeCodePointCount, - const int probability) { - int writingPos = mBuffer->getTailPosition(); - if (!DynamicPatriciaTrieWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer, - 1 /* arraySize */, &writingPos)) { - return false; - } - if (!writePtNodeToBuffer(mBuffer, parentPtNodePos, nodeCodePoints, nodeCodePointCount, - probability, &writingPos)) { - return false; - } - if (!DynamicPatriciaTrieWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer, - NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) { - return false; - } - return true; -} - -// Returns whether the dictionary updating was succeeded or not. -bool DynamicPatriciaTrieWritingHelper::reallocatePtNodeAndAddNewPtNodes( - const DynamicPatriciaTrieNodeReader *const reallocatingPtNode, - const int *const reallocatingPtNodeCodePoints, 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. - // Reallocating PtNode: abcde, newNode: abcxy. - // abc (1st, not terminal) __ de (2nd) - // \_ xy (extra child, terminal) - // Otherwise, this method makes 1st part terminal and write probabilityOfNewPtNode. - // Reallocating PtNode: abcde, newNode: abc. - // abc (1st, terminal) __ de (2nd) - const bool addsExtraChild = newNodeCodePointCount > overlappingCodePointCount; - const int firstPartOfReallocatedPtNodePos = mBuffer->getTailPosition(); - int writingPos = firstPartOfReallocatedPtNodePos; - // 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, - &writingPos)) { - return false; - } - const int actualChildrenPos = writingPos; - // Create new children PtNode array. - const size_t newPtNodeCount = addsExtraChild ? 2 : 1; - if (!DynamicPatriciaTrieWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer, - newPtNodeCount, &writingPos)) { - return false; - } - // Write the 2nd part of the reallocating node. - const int secondPartOfReallocatedPtNodePos = writingPos; - if (!writePtNodeToBufferByCopyingPtNodeInfo(mBuffer, reallocatingPtNode, - firstPartOfReallocatedPtNodePos, - reallocatingPtNodeCodePoints + overlappingCodePointCount, - reallocatingPtNode->getCodePointCount() - overlappingCodePointCount, - reallocatingPtNode->getProbability(), &writingPos)) { - return false; - } - if (addsExtraChild) { - if (!writePtNodeToBuffer(mBuffer, firstPartOfReallocatedPtNodePos, - newNodeCodePoints + overlappingCodePointCount, - newNodeCodePointCount - overlappingCodePointCount, probabilityOfNewPtNode, - &writingPos)) { - return false; - } - } - if (!DynamicPatriciaTrieWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer, - NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) { - return false; - } - // Update original reallocatingPtNode as moved. - if (!markNodeAsMovedAndSetPosition(reallocatingPtNode, firstPartOfReallocatedPtNodePos, - secondPartOfReallocatedPtNodePos)) { - return false; - } - // Load node info. Information of the 1st part will be fetched. - DynamicPatriciaTrieNodeReader nodeReader(mBuffer, mBigramPolicy, mShortcutPolicy); - nodeReader.fetchNodeInfoInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos); - // Update children position. - int childrenPosFieldPos = nodeReader.getChildrenPosFieldPos(); - if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBuffer, - actualChildrenPos, &childrenPosFieldPos)) { - return false; - } - return true; -} - -bool DynamicPatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos, - const HeaderPolicy *const headerPolicy, BufferWithExtendableBuffer *const bufferToWrite, - int *const outUnigramCount, int *const outBigramCount) { - DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy); - readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); - DynamicPatriciaTrieGcEventListeners - ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted - traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted( - headerPolicy, this, mBuffer, mNeedsToDecay); - if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner( - &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) { - return false; - } - if (mNeedsToDecay && traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted - .getValidUnigramCount() > ForgettingCurveUtils::MAX_UNIGRAM_COUNT_AFTER_GC) { - // TODO: Remove more unigrams. - } - - readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); - DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateBigramProbability - traversePolicyToUpdateBigramProbability(mBigramPolicy); - if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner( - &traversePolicyToUpdateBigramProbability)) { - return false; - } - if (mNeedsToDecay && traversePolicyToUpdateBigramProbability.getValidBigramEntryCount() - > ForgettingCurveUtils::MAX_BIGRAM_COUNT_AFTER_GC) { - // TODO: Remove more bigrams. - } - - // Mapping from positions in mBuffer to positions in bufferToWrite. - DictPositionRelocationMap dictPositionRelocationMap; - readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); - DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer - traversePolicyToPlaceAndWriteValidPtNodesToBuffer(this, bufferToWrite, - &dictPositionRelocationMap); - if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner( - &traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) { - return false; - } - - // Create policy instance for the GCed dictionary. - DynamicShortcutListPolicy newDictShortcutPolicy(bufferToWrite); - DynamicBigramListPolicy newDictBigramPolicy(headerPolicy, bufferToWrite, &newDictShortcutPolicy, - mNeedsToDecay); - // Create reading helper for the GCed dictionary. - DynamicPatriciaTrieReadingHelper newDictReadingHelper(bufferToWrite, &newDictBigramPolicy, - &newDictShortcutPolicy); - newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); - DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateAllPositionFields - traversePolicyToUpdateAllPositionFields(this, &newDictBigramPolicy, bufferToWrite, - &dictPositionRelocationMap); - if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner( - &traversePolicyToUpdateAllPositionFields)) { - return false; - } - *outUnigramCount = traversePolicyToUpdateAllPositionFields.getUnigramCount(); - *outBigramCount = traversePolicyToUpdateAllPositionFields.getBigramCount(); - return true; -} - -int DynamicPatriciaTrieWritingHelper::getUpdatedProbability(const int originalProbability, - const int newProbability) { - if (mNeedsToDecay) { - return ForgettingCurveUtils::getUpdatedEncodedProbability(originalProbability, - newProbability); - } else { - return newProbability; - } -} - -} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h deleted file mode 100644 index ca8664729..000000000 --- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.h +++ /dev/null @@ -1,138 +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_WRITING_HELPER_H -#define LATINIME_DYNAMIC_PATRICIA_TRIE_WRITING_HELPER_H - -#include <stdint.h> - -#include "defines.h" -#include "utils/hash_map_compat.h" - -namespace latinime { - -class BufferWithExtendableBuffer; -class DynamicBigramListPolicy; -class DynamicPatriciaTrieNodeReader; -class DynamicPatriciaTrieReadingHelper; -class DynamicShortcutListPolicy; -class HeaderPolicy; - -class DynamicPatriciaTrieWritingHelper { - public: - typedef hash_map_compat<int, int> PtNodeArrayPositionRelocationMap; - typedef hash_map_compat<int, int> PtNodePositionRelocationMap; - struct DictPositionRelocationMap { - public: - DictPositionRelocationMap() - : mPtNodeArrayPositionRelocationMap(), mPtNodePositionRelocationMap() {} - - PtNodeArrayPositionRelocationMap mPtNodeArrayPositionRelocationMap; - PtNodePositionRelocationMap mPtNodePositionRelocationMap; - - private: - DISALLOW_COPY_AND_ASSIGN(DictPositionRelocationMap); - }; - - static const size_t MAX_DICTIONARY_SIZE; - - DynamicPatriciaTrieWritingHelper(BufferWithExtendableBuffer *const buffer, - DynamicBigramListPolicy *const bigramPolicy, - DynamicShortcutListPolicy *const shortcutPolicy, const bool needsToDecay) - : mBuffer(buffer), mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy), - mNeedsToDecay(needsToDecay) {} - - ~DynamicPatriciaTrieWritingHelper() {} - - // Add a word to the dictionary. If the word already exists, update the probability. - bool addUnigramWord(DynamicPatriciaTrieReadingHelper *const readingHelper, - const int *const wordCodePoints, const int codePointCount, const int probability, - bool *const outAddedNewUnigram); - - // Add a bigram relation from word0Pos to word1Pos. - bool addBigramWords(const int word0Pos, const int word1Pos, const int probability, - bool *const outAddedNewBigram); - - // Remove a bigram relation from word0Pos to word1Pos. - bool removeBigramWords(const int word0Pos, const int word1Pos); - - void writeToDictFile(const char *const fileName, const HeaderPolicy *const headerPolicy, - const int unigramCount, const int bigramCount); - - void writeToDictFileWithGC(const int rootPtNodeArrayPos, const char *const fileName, - const HeaderPolicy *const headerPolicy); - - // CAVEAT: This method must be called only from inner classes of - // DynamicPatriciaTrieGcEventListeners. - bool markNodeAsDeleted(const DynamicPatriciaTrieNodeReader *const nodeToUpdate); - - // 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 int *const codePoints, const int codePointCount, const int probability, - int *const writingPos); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTrieWritingHelper); - - static const int CHILDREN_POSITION_FIELD_SIZE; - - BufferWithExtendableBuffer *const mBuffer; - DynamicBigramListPolicy *const mBigramPolicy; - DynamicShortcutListPolicy *const mShortcutPolicy; - const bool mNeedsToDecay; - - bool markNodeAsMovedAndSetPosition(const DynamicPatriciaTrieNodeReader *const nodeToUpdate, - const int movedPos, const int bigramLinkedNodePos); - - bool writePtNodeWithFullInfoToBuffer(BufferWithExtendableBuffer *const bufferToWrite, - const bool isBlacklisted, const bool isNotAWord, - const int parentPos, const int *const codePoints, const int codePointCount, - const int probability, const int childrenPos, const int originalBigramListPos, - const int originalShortcutListPos, int *const writingPos); - - bool writePtNodeToBuffer(BufferWithExtendableBuffer *const bufferToWrite, - const int parentPos, const int *const codePoints, const int codePointCount, - const int probability, int *const writingPos); - - 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 createChildrenPtNodeArrayAndAChildPtNode( - const DynamicPatriciaTrieNodeReader *const parentNode, 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 int probabilityOfNewPtNode, const int *const newNodeCodePoints, - const int newNodeCodePointCount); - - bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy, - BufferWithExtendableBuffer *const bufferToWrite, int *const outUnigramCount, - int *const outBigramCount); - - int getUpdatedProbability(const int originalProbability, const int newProbability); -}; -} // namespace latinime -#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_WRITING_HELPER_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/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h new file mode 100644 index 000000000..12d3579fd --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h @@ -0,0 +1,71 @@ +/* + * 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_SHORTCUT_LIST_POLICY_H +#define LATINIME_VER4_SHORTCUT_LIST_POLICY_H + +#include <stdint.h> + +#include "defines.h" +#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h" +#include "suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h" + +namespace latinime { + +class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy { + public: + Ver4ShortcutListPolicy(const ShortcutDictContent *const shortcutDictContent, + const TerminalPositionLookupTable *const terminalPositionLookupTable) + : mShortcutDictContent(shortcutDictContent), + mTerminalPositionLookupTable(terminalPositionLookupTable) {} + + ~Ver4ShortcutListPolicy() {} + + int getStartPos(const int pos) const { + // The first shortcut entry is located at the head position of the shortcut list. + return pos; + } + + void getNextShortcut(const int maxCodePointCount, int *const outCodePoint, + int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext, + int *const pos) const { + int shortcutFlags = 0; + if (outCodePoint && outCodePointCount) { + mShortcutDictContent->getShortcutEntryAndAdvancePosition(maxCodePointCount, + outCodePoint, outCodePointCount, &shortcutFlags, pos); + } + if (outHasNext) { + *outHasNext = ShortcutListReadingUtils::hasNext(shortcutFlags); + } + if (outIsWhitelist) { + *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(shortcutFlags); + } + } + + void skipAllShortcuts(int *const pos) const { + // Do nothing because we don't need to skip shortcut lists in ver4 dictionaries. + } + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy); + + const ShortcutDictContent *const mShortcutDictContent; + const TerminalPositionLookupTable *const mTerminalPositionLookupTable; +}; +} // namespace latinime +#endif // LATINIME_VER4_SHORTCUT_LIST_POLICY_H 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..063b84cbf --- /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..6a4cfee3c --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h @@ -0,0 +1,235 @@ +/* + * 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_ID), 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); + } + + // PtNode without terminal id. + 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_ID), + mProbabilityFieldPos(probabilityFieldPos), mProbability(probability), + mChildrenPosFieldPos(childrenPosFieldPos), mChildrenPos(childrenPos), + mBigramLinkedNodePos(bigramLinkedNodePos), mShortcutPos(shortcutPos), + mBigramPos(bigramPos), mSiblingPos(siblingPos) { + memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount); + } + + // PtNode with a terminal id. + PtNodeParams(const int headPos, const PatriciaTrieReadingUtils::NodeFlags flags, + const int parentPos, const int codePointCount, const int *const codePoints, + const int terminalIdFieldPos, const int terminalId, const int probability, + const int childrenPosFieldPos, const int childrenPos, const int bigramLinkedNodePos, + const int siblingPos) + : mHeadPos(headPos), mFlags(flags), mParentPos(parentPos), + mCodePointCount(codePointCount), mCodePoints(), + mTerminalIdFieldPos(terminalIdFieldPos), mTerminalId(terminalId), + mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability), + mChildrenPosFieldPos(childrenPosFieldPos), mChildrenPos(childrenPos), + mBigramLinkedNodePos(bigramLinkedNodePos), mShortcutPos(terminalId), + mBigramPos(terminalId), mSiblingPos(siblingPos) { + memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount); + } + + // Construct new params by updating existing PtNode params. + PtNodeParams(const PtNodeParams *const ptNodeParams, + const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos, + const int codePointCount, const int *const codePoints, const int probability) + : mHeadPos(ptNodeParams->getHeadPos()), mFlags(flags), mParentPos(parentPos), + mCodePointCount(codePointCount), mCodePoints(), + mTerminalIdFieldPos(ptNodeParams->getTerminalIdFieldPos()), + mTerminalId(ptNodeParams->getTerminalId()), + mProbabilityFieldPos(ptNodeParams->getProbabilityFieldPos()), + mProbability(probability), + mChildrenPosFieldPos(ptNodeParams->getChildrenPosFieldPos()), + mChildrenPos(ptNodeParams->getChildrenPos()), + mBigramLinkedNodePos(ptNodeParams->getBigramLinkedNodePos()), + mShortcutPos(ptNodeParams->getShortcutPos()), + mBigramPos(ptNodeParams->getBigramsPos()), + mSiblingPos(ptNodeParams->getSiblingNodePos()) { + memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount); + } + + PtNodeParams(const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos, + const int codePointCount, const int *const codePoints, const int probability) + : mHeadPos(NOT_A_DICT_POS), mFlags(flags), mParentPos(parentPos), + mCodePointCount(codePointCount), mCodePoints(), + mTerminalIdFieldPos(NOT_A_DICT_POS), + mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID), + mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(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) { + 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/structure/pt_common/pt_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h new file mode 100644 index 000000000..0f1e635bc --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h @@ -0,0 +1,59 @@ +/* + * 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_WRITER_H +#define LATINIME_PT_NODE_WRITER_H + +#include "defines.h" + +#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h" + +namespace latinime { + +// Interface class used to write PtNode information. +class PtNodeWriter { + public: + virtual ~PtNodeWriter() {} + + virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams) = 0; + + virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int movedPos, const int bigramLinkedNodePos) = 0; + + virtual bool updatePtNodeProbability(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int probability) = 0; + + virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int newChildrenPosition) = 0; + + virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams, + int *const ptNodeWritingPos) = 0; + + virtual bool addNewBigramEntry(const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam, const int probability, + bool *const outAddedNewBigram) = 0; + + virtual bool removeBigramEntry(const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam) = 0; + + protected: + PtNodeWriter() {}; + + private: + DISALLOW_COPY_AND_ASSIGN(PtNodeWriter); +}; +} // namespace latinime +#endif /* LATINIME_PT_NODE_WRITER_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..a252c6fb2 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,27 @@ * 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/structure/pt_common/pt_node_writer.h" +#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.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 +46,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 +56,12 @@ bool DynamicPatriciaTrieGcEventListeners } if (isUselessPtNode) { // Current PtNode is no longer needed. Mark it as deleted. - if (!mWritingHelper->markNodeAsDeleted(node)) { + if (!mPtNodeWriter->markPtNodeAsDeleted(ptNodeParams)) { return false; } } else { mValueStack.back() += 1; - if (node->isTerminal()) { + if (ptNodeParams->isTerminal()) { mValidUnigramCount += 1; } } @@ -67,10 +69,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 +118,27 @@ 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 mPtNodeWriter->writePtNodeAndAdvancePosition(ptNodeParams, &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..a0b3b4d3a 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/utils/buffer_with_extendable_buffer.h" #include "utils/hash_map_compat.h" namespace latinime { class DictionaryHeaderStructurePolicy; +class PtNodeWriter; +class PtNodeParams; class DynamicPatriciaTrieGcEventListeners { public: @@ -41,9 +42,9 @@ class DynamicPatriciaTrieGcEventListeners { public: TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted( const DictionaryHeaderStructurePolicy *const headerPolicy, - DynamicPatriciaTrieWritingHelper *const writingHelper, - BufferWithExtendableBuffer *const buffer, const bool isDecayingDict) - : mHeaderPolicy(headerPolicy), mWritingHelper(writingHelper), mBuffer(buffer), + PtNodeWriter *const ptNodeWriter, BufferWithExtendableBuffer *const buffer, + const bool isDecayingDict) + : mHeaderPolicy(headerPolicy), mPtNodeWriter(ptNodeWriter), mBuffer(buffer), mIsDecayingDict(isDecayingDict), mValueStack(), mChildrenValue(0), mValidUnigramCount(0) {} @@ -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; @@ -78,7 +78,7 @@ class DynamicPatriciaTrieGcEventListeners { TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted); const DictionaryHeaderStructurePolicy *const mHeaderPolicy; - DynamicPatriciaTrieWritingHelper *const mWritingHelper; + PtNodeWriter *const mPtNodeWriter; BufferWithExtendableBuffer *const mBuffer; const bool mIsDecayingDict; std::vector<int> mValueStack; @@ -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; @@ -119,11 +118,10 @@ class DynamicPatriciaTrieGcEventListeners { : public DynamicPatriciaTrieReadingHelper::TraversingEventListener { public: TraversePolicyToPlaceAndWriteValidPtNodesToBuffer( - DynamicPatriciaTrieWritingHelper *const writingHelper, - BufferWithExtendableBuffer *const bufferToWrite, + PtNodeWriter *const ptNodeWriter, BufferWithExtendableBuffer *const bufferToWrite, DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const dictPositionRelocationMap) - : mWritingHelper(writingHelper), mBufferToWrite(bufferToWrite), + : mPtNodeWriter(ptNodeWriter), mBufferToWrite(bufferToWrite), mDictPositionRelocationMap(dictPositionRelocationMap), mValidPtNodeCount(0), mPtNodeArraySizeFieldPos(NOT_A_DICT_POS) {}; @@ -133,13 +131,12 @@ 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); - DynamicPatriciaTrieWritingHelper *const mWritingHelper; + PtNodeWriter *const mPtNodeWriter; BufferWithExtendableBuffer *const mBufferToWrite; DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const mDictPositionRelocationMap; @@ -151,13 +148,11 @@ class DynamicPatriciaTrieGcEventListeners { : public DynamicPatriciaTrieReadingHelper::TraversingEventListener { public: TraversePolicyToUpdateAllPositionFields( - DynamicPatriciaTrieWritingHelper *const writingHelper, DynamicBigramListPolicy *const bigramPolicy, BufferWithExtendableBuffer *const bufferToWrite, const DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const dictPositionRelocationMap) - : mWritingHelper(writingHelper), mBigramPolicy(bigramPolicy), - mBufferToWrite(bufferToWrite), + : mBigramPolicy(bigramPolicy), mBufferToWrite(bufferToWrite), mDictPositionRelocationMap(dictPositionRelocationMap), mUnigramCount(0), mBigramCount(0) {}; @@ -167,8 +162,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; @@ -181,7 +175,6 @@ class DynamicPatriciaTrieGcEventListeners { private: DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPositionFields); - DynamicPatriciaTrieWritingHelper *const mWritingHelper; DynamicBigramListPolicy *const mBigramPolicy; BufferWithExtendableBuffer *const mBufferToWrite; const DynamicPatriciaTrieWritingHelper::DictPositionRelocationMap *const 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..ef0067b48 --- /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/structure/v3/dynamic_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_writer.cpp new file mode 100644 index 000000000..3b1e16cc7 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_writer.cpp @@ -0,0 +1,236 @@ +/* + * 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_writer.h" + +#include "suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h" +#include "suggest/policyimpl/dictionary/shortcut/dynamic_shortcut_list_policy.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_utils.h" +#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_utils.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" + +namespace latinime { + +const int DynamicPatriciaTrieNodeWriter::CHILDREN_POSITION_FIELD_SIZE = 3; + +bool DynamicPatriciaTrieNodeWriter::markPtNodeAsDeleted( + const PtNodeParams *const toBeUpdatedPtNodeParams) { + int pos = toBeUpdatedPtNodeParams->getHeadPos(); + const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(pos); + const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer); + if (usesAdditionalBuffer) { + pos -= mBuffer->getOriginalBufferSize(); + } + // Read original flags + const PatriciaTrieReadingUtils::NodeFlags originalFlags = + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos); + const PatriciaTrieReadingUtils::NodeFlags updatedFlags = + DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */, + true /* isDeleted */); + int writingPos = toBeUpdatedPtNodeParams->getHeadPos(); + // Update flags. + return DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags, + &writingPos); +} + +bool DynamicPatriciaTrieNodeWriter::markPtNodeAsMoved( + const PtNodeParams *const toBeUpdatedPtNodeParams, + const int movedPos, const int bigramLinkedNodePos) { + int pos = toBeUpdatedPtNodeParams->getHeadPos(); + const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(pos); + const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer); + if (usesAdditionalBuffer) { + pos -= mBuffer->getOriginalBufferSize(); + } + // Read original flags + const PatriciaTrieReadingUtils::NodeFlags originalFlags = + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos); + const PatriciaTrieReadingUtils::NodeFlags updatedFlags = + DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */, + false /* isDeleted */); + int writingPos = toBeUpdatedPtNodeParams->getHeadPos(); + // Update flags. + if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, updatedFlags, + &writingPos)) { + return false; + } + // Update moved position, which is stored in the parent offset field. + if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition( + mBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) { + return false; + } + // Update bigram linked node position, which is stored in the children position field. + int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos(); + if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition( + mBuffer, bigramLinkedNodePos, &childrenPosFieldPos)) { + return false; + } + if (toBeUpdatedPtNodeParams->hasChildren()) { + // Update children's parent position. + mReadingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos()); + while (!mReadingHelper.isEnd()) { + const PtNodeParams childPtNodeParams(mReadingHelper.getPtNodeParams()); + int parentOffsetFieldPos = childPtNodeParams.getHeadPos() + + DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE; + if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition( + 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; + } + mReadingHelper.readNextSiblingNode(childPtNodeParams); + } + } + return true; +} + +bool DynamicPatriciaTrieNodeWriter::updatePtNodeProbability( + const PtNodeParams *const toBeUpdatedPtNodeParams, const int newProbability) { + if (!toBeUpdatedPtNodeParams->isTerminal()) { + return false; + } + int probabilityFieldPos = toBeUpdatedPtNodeParams->getProbabilityFieldPos(); + return DynamicPatriciaTrieWritingUtils::writeProbabilityAndAdvancePosition(mBuffer, + newProbability, &probabilityFieldPos); +} + +bool DynamicPatriciaTrieNodeWriter::updateChildrenPosition( + const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) { + int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos(); + return DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBuffer, + newChildrenPosition, &childrenPosFieldPos); +} + +bool DynamicPatriciaTrieNodeWriter::writePtNodeAndAdvancePosition( + const PtNodeParams *const ptNodeParams, int *const ptNodeWritingPos) { + const int nodePos = *ptNodeWritingPos; + // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the + // PtNode writing. + if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, + 0 /* nodeFlags */, ptNodeWritingPos)) { + return false; + } + // Calculate a parent offset and write the offset. + if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition(mBuffer, + ptNodeParams->getParentPos(), nodePos, ptNodeWritingPos)) { + return false; + } + // Write code points + if (!DynamicPatriciaTrieWritingUtils::writeCodePointsAndAdvancePosition(mBuffer, + ptNodeParams->getCodePoints(), ptNodeParams->getCodePointCount(), ptNodeWritingPos)) { + return false; + } + // Write probability when the probability is a valid probability, which means this node is + // terminal. + if (ptNodeParams->getProbability() != NOT_A_PROBABILITY) { + if (!DynamicPatriciaTrieWritingUtils::writeProbabilityAndAdvancePosition(mBuffer, + ptNodeParams->getProbability(), ptNodeWritingPos)) { + return false; + } + } + // Write children position + if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mBuffer, + ptNodeParams->getChildrenPos(), ptNodeWritingPos)) { + return false; + } + // Copy shortcut list when the originalShortcutListPos is valid dictionary position. + if (ptNodeParams->getShortcutPos() != NOT_A_DICT_POS) { + int fromPos = ptNodeParams->getShortcutPos(); + if (!mShortcutPolicy->copyAllShortcutsAndReturnIfSucceededOrNot(mBuffer, &fromPos, + ptNodeWritingPos)) { + return false; + } + } + // Copy bigram list when the originalBigramListPos is valid dictionary position. + int bigramCount = 0; + if (ptNodeParams->getBigramsPos() != NOT_A_DICT_POS) { + int fromPos = ptNodeParams->getBigramsPos(); + if (!mBigramPolicy->copyAllBigrams(mBuffer, &fromPos, ptNodeWritingPos, &bigramCount)) { + return false; + } + } + // Create node flags and write them. + PatriciaTrieReadingUtils::NodeFlags nodeFlags = + PatriciaTrieReadingUtils::createAndGetFlags(ptNodeParams->isBlacklisted(), + ptNodeParams->isNotAWord(), + ptNodeParams->getProbability() != NOT_A_PROBABILITY /* isTerminal */, + ptNodeParams->getShortcutPos() != NOT_A_DICT_POS /* hasShortcutTargets */, + bigramCount > 0 /* hasBigrams */, + ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */, + CHILDREN_POSITION_FIELD_SIZE); + int flagsFieldPos = nodePos; + if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mBuffer, nodeFlags, + &flagsFieldPos)) { + return false; + } + return true; +} + +bool DynamicPatriciaTrieNodeWriter::addNewBigramEntry( + const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam, const int probability, + bool *const outAddedNewBigram) { + const int newNodePos = mBuffer->getTailPosition(); + int writingPos = newNodePos; + // Write a new PtNode using original PtNode's info to the tail of the dictionary in mBuffer. + if (!writePtNodeAndAdvancePosition(sourcePtNodeParams, &writingPos)) { + return false; + } + if (!markPtNodeAsMoved(sourcePtNodeParams, newNodePos, newNodePos)) { + return false; + } + const PtNodeParams newPtNodeParams( + mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(newNodePos)); + if (newPtNodeParams.getBigramsPos() != NOT_A_DICT_POS) { + // Insert a new bigram entry into the existing bigram list. + int bigramListPos = newPtNodeParams.getBigramsPos(); + return mBigramPolicy->addNewBigramEntryToBigramList(targetPtNodeParam->getHeadPos(), + probability, &bigramListPos, outAddedNewBigram); + } else { + // The PtNode doesn't have a bigram list. + *outAddedNewBigram = true; + // First, Write a bigram entry at the tail position of the PtNode. + if (!mBigramPolicy->writeNewBigramEntry(targetPtNodeParam->getHeadPos(), probability, + &writingPos)) { + return false; + } + // Then, Mark as the PtNode having bigram list in the flags. + const PatriciaTrieReadingUtils::NodeFlags updatedFlags = + 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, + &writingPos); + } +} + +bool DynamicPatriciaTrieNodeWriter::removeBigramEntry( + const PtNodeParams *const sourcePtNodeParams, const PtNodeParams *const targetPtNodeParam) { + if (sourcePtNodeParams->getBigramsPos() == NOT_A_DICT_POS) { + return false; + } + return mBigramPolicy->removeBigram(sourcePtNodeParams->getBigramsPos(), + targetPtNodeParam->getHeadPos()); +} + +} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_writer.h new file mode 100644 index 000000000..87ed1b159 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_node_writer.h @@ -0,0 +1,82 @@ +/* + * 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_WRITER_H +#define LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_WRITER_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_writer.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" + +namespace latinime { + +class BufferWithExtendableBuffer; +class DynamicBigramListPolicy; +class DynamicShortcutListPolicy; + +/* + * This class is used for helping to writes nodes of dynamic patricia trie. + */ +class DynamicPatriciaTrieNodeWriter : public PtNodeWriter { + public: + DynamicPatriciaTrieNodeWriter(BufferWithExtendableBuffer *const buffer, + const DynamicPatriciaTrieNodeReader *const ptNodeReader, + DynamicBigramListPolicy *const bigramPolicy, + DynamicShortcutListPolicy *const shortcutPolicy) + : mBuffer(buffer), mPtNodeReader(ptNodeReader), mReadingHelper(mBuffer, ptNodeReader), + mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy) {} + + virtual ~DynamicPatriciaTrieNodeWriter() {} + + virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams); + + virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int movedPos, const int bigramLinkedNodePos); + + virtual bool updatePtNodeProbability(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int newProbability); + + virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int newChildrenPosition); + + virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams, + int *const ptNodeWritingPos); + + virtual bool addNewBigramEntry(const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam, const int probability, + bool *const outAddedNewBigram); + + virtual bool removeBigramEntry(const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam); + + private: + DISALLOW_COPY_AND_ASSIGN(DynamicPatriciaTrieNodeWriter); + + static const int CHILDREN_POSITION_FIELD_SIZE; + + BufferWithExtendableBuffer *const mBuffer; + const DynamicPatriciaTrieNodeReader *const mPtNodeReader; + DynamicPatriciaTrieReadingHelper mReadingHelper; + DynamicBigramListPolicy *const mBigramPolicy; + DynamicShortcutListPolicy *const mShortcutPolicy; + +}; +} // namespace latinime +#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_NODE_WRITER_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..6b58f5fb7 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,12 @@ #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_updating_helper.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,118 +46,49 @@ 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); } } int DynamicPatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount( const int ptNodePos, const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) const { - // 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()); - // First, read the terminal node and get its probability. + DynamicPatriciaTrieReadingHelper readingHelper(&mBufferWithExtendableBuffer, &mNodeReader); readingHelper.initWithPtNodePos(ptNodePos); - if (!readingHelper.isValidTerminalNode()) { - // Node at the ptNodePos is not a valid terminal node. - *outUnigramProbability = NOT_A_PROBABILITY; - return 0; - } - // Store terminal node probability. - *outUnigramProbability = readingHelper.getNodeReader()->getProbability(); - // Then, following parent node link to the dictionary root and fetch node code points. - while (!readingHelper.isEnd()) { - if (readingHelper.getTotalCodePointCount() > 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.getPrevTotalCodePointCount(), reverseCodePoints); - // Follow parent node toward the root node. - readingHelper.readParentNode(); - } - if (readingHelper.isError()) { - // The node position or the dictionary is invalid. - *outUnigramProbability = NOT_A_PROBABILITY; - 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]; - } - return codePointCount; + return readingHelper.getCodePointsAndProbabilityAndReturnCodePointCount(maxCodePointCount, + outCodePoints, outUnigramProbability); } -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 int matchedCodePointCount = readingHelper.getPrevTotalCodePointCount(); - if (readingHelper.getTotalCodePointCount() > length - || !readingHelper.isMatchedCodePoint(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(); - continue; - } - // Check following merged node code points. - const int nodeCodePointCount = nodeReader->getCodePointCount(); - for (int j = 1; j < nodeCodePointCount; ++j) { - if (!readingHelper.isMatchedCodePoint( - 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()) { - // Terminal position is found. - return nodeReader->getHeadPos(); - } - if (!nodeReader->hasChildren()) { - return NOT_A_DICT_POS; - } - // Advance to the children nodes. - readingHelper.readChildNode(); - } - // If we already traversed the tree further than the word is long, there means - // there was no match (or we would have found it). - return NOT_A_DICT_POS; + return readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch); } int DynamicPatriciaTriePolicy::getProbability(const int unigramProbability, @@ -179,44 +111,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,13 +151,10 @@ 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()); bool addedNewUnigram = false; - if (writingHelper.addUnigramWord(&readingHelper, word, length, probability, + if (mUpdatingHelper.addUnigramWord(&readingHelper, word, length, probability, &addedNewUnigram)) { if (addedNewUnigram) { mUnigramCount++; @@ -244,7 +167,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,20 +176,18 @@ 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; } - DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer, - &mBigramListPolicy, &mShortcutListPolicy, mHeaderPolicy.isDecayingDict()); bool addedNewBigram = false; - if (writingHelper.addBigramWords(word0Pos, word1Pos, probability, &addedNewBigram)) { + if (mUpdatingHelper.addBigramWords(word0Pos, word1Pos, probability, &addedNewBigram)) { if (addedNewBigram) { mBigramCount++; } @@ -278,7 +199,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,19 +208,17 @@ 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; } - DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer, - &mBigramListPolicy, &mShortcutListPolicy, mHeaderPolicy.isDecayingDict()); - if (writingHelper.removeBigramWords(word0Pos, word1Pos)) { + if (mUpdatingHelper.removeBigramWords(word0Pos, word1Pos)) { mBigramCount--; return true; } else { @@ -308,17 +227,17 @@ 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; } - DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer, - &mBigramListPolicy, &mShortcutListPolicy, false /* needsToDecay */); + DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer, &mNodeReader, + &mNodeWriter, &mBigramListPolicy, &mShortcutListPolicy, false /* needsToDecay */); writingHelper.writeToDictFile(filePath, &mHeaderPolicy, mUnigramCount, mBigramCount); } void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) { - if (!mBuffer->isUpdatable()) { + if (!mMmappedBuffer.get()->isUpdatable()) { AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary."); return; } @@ -327,14 +246,14 @@ void DynamicPatriciaTriePolicy::flushWithGC(const char *const filePath) { false /* mindsBlockByDecay */, mUnigramCount, mBigramCount, &mHeaderPolicy)); DynamicBigramListPolicy bigramListPolicyForGC(&mHeaderPolicy, &mBufferWithExtendableBuffer, &mShortcutListPolicy, needsToDecay); - DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer, - &bigramListPolicyForGC, &mShortcutListPolicy, needsToDecay); + DynamicPatriciaTrieWritingHelper writingHelper(&mBufferWithExtendableBuffer, &mNodeReader, + &mNodeWriter, &bigramListPolicyForGC, &mShortcutListPolicy, needsToDecay); writingHelper.writeToDictFileWithGC(getRootPosition(), filePath, &mHeaderPolicy); mNeedsToDecayForTesting = false; } 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..454698430 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,11 @@ #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/structure/v3/dynamic_patricia_trie_node_writer.h" +#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_updating_helper.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 +36,37 @@ 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), + mNodeWriter(&mBufferWithExtendableBuffer, &mNodeReader, &mBigramListPolicy, + &mShortcutListPolicy), + mUpdatingHelper(&mBufferWithExtendableBuffer, &mNodeReader, &mNodeWriter, + mHeaderPolicy.isDecayingDict()), 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 +117,14 @@ 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; + DynamicPatriciaTrieNodeWriter mNodeWriter; + DynamicPatriciaTrieUpdatingHelper mUpdatingHelper; 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..b3fdbeb78 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,18 @@ * 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" +#include "utils/char_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 +40,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 +108,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 +131,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 +147,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; @@ -158,6 +169,92 @@ bool DynamicPatriciaTrieReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreor return !isError(); } +int DynamicPatriciaTrieReadingHelper::getCodePointsAndProbabilityAndReturnCodePointCount( + const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) { + // 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]; + const PtNodeParams terminalPtNodeParams(getPtNodeParams()); + // First, read the terminal node and get its probability. + if (!isValidTerminalNode(terminalPtNodeParams)) { + // Node at the ptNodePos is not a valid terminal node. + *outUnigramProbability = NOT_A_PROBABILITY; + return 0; + } + // Store terminal node probability. + *outUnigramProbability = terminalPtNodeParams.getProbability(); + // Then, following parent node link to the dictionary root and fetch node code points. + int totalCodePointCount = 0; + while (!isEnd()) { + const PtNodeParams ptNodeParams(getPtNodeParams()); + totalCodePointCount = 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. + fetchMergedNodeCodePointsInReverseOrder(ptNodeParams, getPrevTotalCodePointCount(), + reverseCodePoints); + // Follow parent node toward the root node. + readParentNode(ptNodeParams); + } + if (isError()) { + // The node position or the dictionary is invalid. + *outUnigramProbability = NOT_A_PROBABILITY; + return 0; + } + // Reverse the stored code points to output them. + for (int i = 0; i < totalCodePointCount; ++i) { + outCodePoints[i] = reverseCodePoints[totalCodePointCount - i - 1]; + } + return totalCodePointCount; +} + +int DynamicPatriciaTrieReadingHelper::getTerminalPtNodePositionOfWord(const int *const inWord, + const int length, const bool forceLowerCaseSearch) { + int searchCodePoints[length]; + for (int i = 0; i < length; ++i) { + searchCodePoints[i] = forceLowerCaseSearch ? CharUtils::toLowerCase(inWord[i]) : inWord[i]; + } + while (!isEnd()) { + const PtNodeParams ptNodeParams(getPtNodeParams()); + const int matchedCodePointCount = getPrevTotalCodePointCount(); + if (getTotalCodePointCount(ptNodeParams) > length + || !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. + readNextSiblingNode(ptNodeParams); + continue; + } + // Check following merged node code points. + const int nodeCodePointCount = ptNodeParams.getCodePointCount(); + for (int j = 1; j < nodeCodePointCount; ++j) { + if (!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 == getTotalCodePointCount(ptNodeParams)) { + if (!ptNodeParams.isTerminal()) { + return NOT_A_DICT_POS; + } + // Terminal position is found. + return ptNodeParams.getHeadPos(); + } + if (!ptNodeParams.hasChildren()) { + return NOT_A_DICT_POS; + } + // Advance to the children nodes. + 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). + return NOT_A_DICT_POS; +} + // Read node array size and process empty node arrays. Nodes and arrays are counted up in this // method to avoid an infinite loop. void DynamicPatriciaTrieReadingHelper::nextPtNodeArray() { @@ -170,35 +267,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..197027313 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); @@ -215,53 +198,54 @@ class DynamicPatriciaTrieReadingHelper { bool traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner( TraversingEventListener *const listener); + int getCodePointsAndProbabilityAndReturnCodePointCount(const int maxCodePointCount, + int *const outCodePoints, int *const outUnigramProbability); + + int getTerminalPtNodePositionOfWord(const int *const inWord, const int length, + const bool forceLowerCaseSearch); + 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 +263,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/structure/v3/dynamic_patricia_trie_updating_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_updating_helper.cpp new file mode 100644 index 000000000..cbc0d2304 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_updating_helper.cpp @@ -0,0 +1,279 @@ +/* + * 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_updating_helper.h" + +#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h" +#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h" +#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h" +#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_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 "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h" + +namespace latinime { + +const int DynamicPatriciaTrieUpdatingHelper::CHILDREN_POSITION_FIELD_SIZE = 3; + +bool DynamicPatriciaTrieUpdatingHelper::addUnigramWord( + DynamicPatriciaTrieReadingHelper *const readingHelper, + const int *const wordCodePoints, const int codePointCount, const int probability, + 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(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(ptNodeParams); + continue; + } + // Check following merged node code points. + const int nodeCodePointCount = ptNodeParams.getCodePointCount(); + for (int j = 1; j < nodeCodePointCount; ++j) { + const int nextIndex = matchedCodePointCount + j; + if (nextIndex >= codePointCount || !readingHelper->isMatchedCodePoint(ptNodeParams, j, + wordCodePoints[matchedCodePointCount + j])) { + *outAddedNewUnigram = true; + return reallocatePtNodeAndAddNewPtNodes(&ptNodeParams, j, + getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, + probability), + wordCodePoints + matchedCodePointCount, + codePointCount - matchedCodePointCount); + } + } + // All characters are matched. + if (codePointCount == readingHelper->getTotalCodePointCount(ptNodeParams)) { + return setPtNodeProbability(&ptNodeParams, probability, outAddedNewUnigram); + } + if (!ptNodeParams.hasChildren()) { + *outAddedNewUnigram = true; + return createChildrenPtNodeArrayAndAChildPtNode(&ptNodeParams, + getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability), + wordCodePoints + readingHelper->getTotalCodePointCount(ptNodeParams), + codePointCount - readingHelper->getTotalCodePointCount(ptNodeParams)); + } + // Advance to the children nodes. + parentPos = ptNodeParams.getHeadPos(); + readingHelper->readChildNode(ptNodeParams); + } + if (readingHelper->isError()) { + // The dictionary is invalid. + return false; + } + int pos = readingHelper->getPosOfLastForwardLinkField(); + *outAddedNewUnigram = true; + return createAndInsertNodeIntoPtNodeArray(parentPos, + wordCodePoints + readingHelper->getPrevTotalCodePointCount(), + codePointCount - readingHelper->getPrevTotalCodePointCount(), + getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability), &pos); +} + +bool DynamicPatriciaTrieUpdatingHelper::addBigramWords(const int word0Pos, const int word1Pos, + const int probability, bool *const outAddedNewBigram) { + const PtNodeParams sourcePtNodeParams( + mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word0Pos)); + const PtNodeParams targetPtNodeParams( + mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word1Pos)); + return mPtNodeWriter->addNewBigramEntry(&sourcePtNodeParams, &targetPtNodeParams, probability, + outAddedNewBigram); +} + +// Remove a bigram relation from word0Pos to word1Pos. +bool DynamicPatriciaTrieUpdatingHelper::removeBigramWords(const int word0Pos, const int word1Pos) { + const PtNodeParams sourcePtNodeParams( + mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word0Pos)); + const PtNodeParams targetPtNodeParams( + mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(word1Pos)); + return mPtNodeWriter->removeBigramEntry(&sourcePtNodeParams, &targetPtNodeParams); +} + +bool DynamicPatriciaTrieUpdatingHelper::createAndInsertNodeIntoPtNodeArray(const int parentPos, + const int *const nodeCodePoints, const int nodeCodePointCount, const int probability, + int *const forwardLinkFieldPos) { + const int newPtNodeArrayPos = mBuffer->getTailPosition(); + if (!DynamicPatriciaTrieWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer, + newPtNodeArrayPos, forwardLinkFieldPos)) { + return false; + } + return createNewPtNodeArrayWithAChildPtNode(parentPos, nodeCodePoints, nodeCodePointCount, + probability); +} + +bool DynamicPatriciaTrieUpdatingHelper::setPtNodeProbability( + const PtNodeParams *const originalPtNodeParams, const int probability, + bool *const outAddedNewUnigram) { + if (originalPtNodeParams->isTerminal()) { + // Overwrites the probability. + *outAddedNewUnigram = false; + const int probabilityToWrite = getUpdatedProbability( + originalPtNodeParams->getProbability(), probability); + return mPtNodeWriter->updatePtNodeProbability(originalPtNodeParams, probabilityToWrite); + } else { + // Make the node terminal and write the probability. + *outAddedNewUnigram = true; + const int movedPos = mBuffer->getTailPosition(); + int writingPos = movedPos; + const PtNodeParams ptNodeParamsToWrite(getUpdatedPtNodeParams(originalPtNodeParams, + originalPtNodeParams->getParentPos(), originalPtNodeParams->getCodePointCount(), + originalPtNodeParams->getCodePoints(), + getUpdatedProbability(NOT_A_PROBABILITY /* originalProbability */, probability))); + if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&ptNodeParamsToWrite, &writingPos)) { + return false; + } + if (!mPtNodeWriter->markPtNodeAsMoved(originalPtNodeParams, movedPos, movedPos)) { + return false; + } + } + return true; +} + +bool DynamicPatriciaTrieUpdatingHelper::createChildrenPtNodeArrayAndAChildPtNode( + const PtNodeParams *const parentPtNodeParams, const int probability, + const int *const codePoints, const int codePointCount) { + const int newPtNodeArrayPos = mBuffer->getTailPosition(); + if (!mPtNodeWriter->updateChildrenPosition(parentPtNodeParams, newPtNodeArrayPos)) { + return false; + } + return createNewPtNodeArrayWithAChildPtNode(parentPtNodeParams->getHeadPos(), codePoints, + codePointCount, probability); +} + +bool DynamicPatriciaTrieUpdatingHelper::createNewPtNodeArrayWithAChildPtNode( + const int parentPtNodePos, const int *const nodeCodePoints, const int nodeCodePointCount, + const int probability) { + int writingPos = mBuffer->getTailPosition(); + if (!DynamicPatriciaTrieWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer, + 1 /* arraySize */, &writingPos)) { + return false; + } + const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode( + parentPtNodePos, nodeCodePointCount, nodeCodePoints, probability)); + if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&ptNodeParamsToWrite, &writingPos)) { + return false; + } + if (!DynamicPatriciaTrieWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer, + NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) { + return false; + } + return true; +} + +// Returns whether the dictionary updating was succeeded or not. +bool DynamicPatriciaTrieUpdatingHelper::reallocatePtNodeAndAddNewPtNodes( + 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. + // Reallocating PtNode: abcde, newNode: abcxy. + // abc (1st, not terminal) __ de (2nd) + // \_ xy (extra child, terminal) + // Otherwise, this method makes 1st part terminal and write probabilityOfNewPtNode. + // Reallocating PtNode: abcde, newNode: abc. + // abc (1st, terminal) __ de (2nd) + const bool addsExtraChild = newNodeCodePointCount > overlappingCodePointCount; + const int firstPartOfReallocatedPtNodePos = mBuffer->getTailPosition(); + int writingPos = firstPartOfReallocatedPtNodePos; + // 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; + const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode( + reallocatingPtNodeParams->getParentPos(), overlappingCodePointCount, + reallocatingPtNodeParams->getCodePoints(), newProbability)); + if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&ptNodeParamsToWrite, &writingPos)) { + return false; + } + const int actualChildrenPos = writingPos; + // Create new children PtNode array. + const size_t newPtNodeCount = addsExtraChild ? 2 : 1; + if (!DynamicPatriciaTrieWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer, + newPtNodeCount, &writingPos)) { + return false; + } + // Write the 2nd part of the reallocating node. + const int secondPartOfReallocatedPtNodePos = writingPos; + const PtNodeParams childPartPtNodeParams(getUpdatedPtNodeParams(reallocatingPtNodeParams, + firstPartOfReallocatedPtNodePos, + reallocatingPtNodeParams->getCodePointCount() - overlappingCodePointCount, + reallocatingPtNodeParams->getCodePoints() + overlappingCodePointCount, + reallocatingPtNodeParams->getProbability())); + if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&childPartPtNodeParams, &writingPos)) { + return false; + } + if (addsExtraChild) { + const PtNodeParams extraChildPtNodeParams(getPtNodeParamsForNewPtNode( + firstPartOfReallocatedPtNodePos, newNodeCodePointCount - overlappingCodePointCount, + newNodeCodePoints + overlappingCodePointCount, probabilityOfNewPtNode)); + if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&extraChildPtNodeParams, &writingPos)) { + return false; + } + } + if (!DynamicPatriciaTrieWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer, + NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) { + return false; + } + // Update original reallocating PtNode as moved. + if (!mPtNodeWriter->markPtNodeAsMoved(reallocatingPtNodeParams, firstPartOfReallocatedPtNodePos, + secondPartOfReallocatedPtNodePos)) { + return false; + } + // Load node info. Information of the 1st part will be fetched. + const PtNodeParams ptNodeParams( + mPtNodeReader->fetchNodeInfoInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos)); + // Update children position. + return mPtNodeWriter->updateChildrenPosition(&ptNodeParams, actualChildrenPos); +} + +int DynamicPatriciaTrieUpdatingHelper::getUpdatedProbability(const int originalProbability, + const int newProbability) const { + if (mNeedsToDecay) { + return ForgettingCurveUtils::getUpdatedEncodedProbability(originalProbability, + newProbability); + } else { + return newProbability; + } +} + +const PtNodeParams DynamicPatriciaTrieUpdatingHelper::getUpdatedPtNodeParams( + const PtNodeParams *const originalPtNodeParams, const int parentPos, + const int codePointCount, const int *const codePoints, const int probability) const { + const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags( + originalPtNodeParams->isBlacklisted(), originalPtNodeParams->isNotAWord(), + probability != NOT_A_PROBABILITY /* isTerminal */, + originalPtNodeParams->getShortcutPos() != NOT_A_DICT_POS /* hasShortcutTargets */, + originalPtNodeParams->getBigramsPos() != NOT_A_DICT_POS /* hasBigrams */, + codePointCount > 1 /* hasMultipleChars */, CHILDREN_POSITION_FIELD_SIZE); + return PtNodeParams(originalPtNodeParams, flags, parentPos, codePointCount, codePoints, + probability); +} + +const PtNodeParams DynamicPatriciaTrieUpdatingHelper::getPtNodeParamsForNewPtNode( + const int parentPos, const int codePointCount, const int *const codePoints, + const int probability) const { + const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags( + false /* isBlacklisted */, false /* isNotAWord */, + probability != NOT_A_PROBABILITY /* isTerminal */, + false /* hasShortcutTargets */, false /* hasBigrams */, + codePointCount > 1 /* hasMultipleChars */, CHILDREN_POSITION_FIELD_SIZE); + return PtNodeParams(flags, parentPos, codePointCount, codePoints, probability); +} + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_updating_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_updating_helper.h new file mode 100644 index 000000000..b9800cd80 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_updating_helper.h @@ -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. + */ + +#ifndef LATINIME_DYNAMIC_PATRICIA_TRIE_UPDATING_HELPER_H +#define LATINIME_DYNAMIC_PATRICIA_TRIE_UPDATING_HELPER_H + +#include <stdint.h> + +#include "defines.h" +#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h" +#include "utils/hash_map_compat.h" + +namespace latinime { + +class BufferWithExtendableBuffer; +class DynamicPatriciaTrieReadingHelper; +class PtNodeReader; +class PtNodeWriter; + +// TODO: Move to pt_common. +class DynamicPatriciaTrieUpdatingHelper { + public: + DynamicPatriciaTrieUpdatingHelper(BufferWithExtendableBuffer *const buffer, + const PtNodeReader *const ptNodeReader, PtNodeWriter *const ptNodeWriter, + const bool needsToDecay) + : mBuffer(buffer), mPtNodeReader(ptNodeReader), mPtNodeWriter(ptNodeWriter), + mNeedsToDecay(needsToDecay) {} + + ~DynamicPatriciaTrieUpdatingHelper() {} + + // Add a word to the dictionary. If the word already exists, update the probability. + bool addUnigramWord(DynamicPatriciaTrieReadingHelper *const readingHelper, + const int *const wordCodePoints, const int codePointCount, const int probability, + bool *const outAddedNewUnigram); + + // Add a bigram relation from word0Pos to word1Pos. + bool addBigramWords(const int word0Pos, const int word1Pos, const int probability, + bool *const outAddedNewBigram); + + // Remove a bigram relation from word0Pos to word1Pos. + bool removeBigramWords(const int word0Pos, const int word1Pos); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTrieUpdatingHelper); + + static const int CHILDREN_POSITION_FIELD_SIZE; + + BufferWithExtendableBuffer *const mBuffer; + const PtNodeReader *const mPtNodeReader; + PtNodeWriter *const mPtNodeWriter; + const bool mNeedsToDecay; + + bool createAndInsertNodeIntoPtNodeArray(const int parentPos, const int *const nodeCodePoints, + const int nodeCodePointCount, const int probability, int *const forwardLinkFieldPos); + + bool setPtNodeProbability(const PtNodeParams *const originalPtNodeParams, const int probability, + bool *const outAddedNewUnigram); + + 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 PtNodeParams *const reallocatingPtNodeParams, const int overlappingCodePointCount, + const int probabilityOfNewPtNode, const int *const newNodeCodePoints, + const int newNodeCodePointCount); + + int getUpdatedProbability(const int originalProbability, const int newProbability) const; + + const PtNodeParams getUpdatedPtNodeParams(const PtNodeParams *const originalPtNodeParams, + const int parentPos, const int codePointCount, const int *const codePoints, + const int probability) const; + + const PtNodeParams getPtNodeParamsForNewPtNode(const int parentPos, const int codePointCount, + const int *const codePoints, const int probability) const; +}; +} // namespace latinime +#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_UPDATING_HELPER_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.cpp new file mode 100644 index 000000000..d97cec53b --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.cpp @@ -0,0 +1,139 @@ +/* + * 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_writing_helper.h" + +#include "suggest/policyimpl/dictionary/bigram/dynamic_bigram_list_policy.h" +#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h" +#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.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_node_writer.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/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" +#include "utils/hash_map_compat.h" + +namespace latinime { + +// TODO: Make MAX_DICTIONARY_SIZE 8MB. +const size_t DynamicPatriciaTrieWritingHelper::MAX_DICTIONARY_SIZE = 2 * 1024 * 1024; + +void DynamicPatriciaTrieWritingHelper::writeToDictFile(const char *const fileName, + const HeaderPolicy *const headerPolicy, const int unigramCount, const int bigramCount) { + BufferWithExtendableBuffer headerBuffer( + BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE); + const int extendedRegionSize = headerPolicy->getExtendedRegionSize() + + mBuffer->getUsedAdditionalBufferSize(); + if (!headerPolicy->writeHeaderToBuffer(&headerBuffer, false /* updatesLastUpdatedTime */, + false /* updatesLastDecayedTime */, unigramCount, bigramCount, extendedRegionSize)) { + return; + } + DictFileWritingUtils::flushAllHeaderAndBodyToFile(fileName, &headerBuffer, mBuffer); +} + +void DynamicPatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos, + const char *const fileName, const HeaderPolicy *const headerPolicy) { + BufferWithExtendableBuffer newDictBuffer(MAX_DICTIONARY_SIZE); + int unigramCount = 0; + int bigramCount = 0; + if (mNeedsToDecay) { + ForgettingCurveUtils::sTimeKeeper.setCurrentTime(); + } + if (!runGC(rootPtNodeArrayPos, headerPolicy, &newDictBuffer, &unigramCount, &bigramCount)) { + return; + } + BufferWithExtendableBuffer headerBuffer( + BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE); + if (!headerPolicy->writeHeaderToBuffer(&headerBuffer, true /* updatesLastUpdatedTime */, + mNeedsToDecay, unigramCount, bigramCount, 0 /* extendedRegionSize */)) { + return; + } + DictFileWritingUtils::flushAllHeaderAndBodyToFile(fileName, &headerBuffer, &newDictBuffer); +} + +// TODO: Make this method version independent. +bool DynamicPatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos, + const HeaderPolicy *const headerPolicy, BufferWithExtendableBuffer *const bufferToWrite, + int *const outUnigramCount, int *const outBigramCount) { + DynamicPatriciaTrieNodeReader ptNodeReader(mBuffer, mBigramPolicy, mShortcutPolicy); + DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, &ptNodeReader); + readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); + DynamicPatriciaTrieGcEventListeners + ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted + traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted( + headerPolicy, mPtNodeWriter, mBuffer, mNeedsToDecay); + if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner( + &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) { + return false; + } + if (mNeedsToDecay && traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted + .getValidUnigramCount() > ForgettingCurveUtils::MAX_UNIGRAM_COUNT_AFTER_GC) { + // TODO: Remove more unigrams. + } + + readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); + DynamicPatriciaTrieGcEventListeners::TraversePolicyToUpdateBigramProbability + traversePolicyToUpdateBigramProbability(mBigramPolicy); + if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner( + &traversePolicyToUpdateBigramProbability)) { + return false; + } + if (mNeedsToDecay && traversePolicyToUpdateBigramProbability.getValidBigramEntryCount() + > ForgettingCurveUtils::MAX_BIGRAM_COUNT_AFTER_GC) { + // TODO: Remove more bigrams. + } + + // Mapping from positions in mBuffer to positions in bufferToWrite. + DictPositionRelocationMap dictPositionRelocationMap; + readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos); + DynamicPatriciaTrieNodeWriter newPtNodeWriter(bufferToWrite, + &ptNodeReader, mBigramPolicy, mShortcutPolicy); + DynamicPatriciaTrieGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer + traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&newPtNodeWriter, bufferToWrite, + &dictPositionRelocationMap); + if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner( + &traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) { + return false; + } + + // Create policy instance for the GCed dictionary. + DynamicShortcutListPolicy newDictShortcutPolicy(bufferToWrite); + DynamicBigramListPolicy newDictBigramPolicy(headerPolicy, bufferToWrite, &newDictShortcutPolicy, + mNeedsToDecay); + // 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(&newDictBigramPolicy, bufferToWrite, + &dictPositionRelocationMap); + if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner( + &traversePolicyToUpdateAllPositionFields)) { + return false; + } + *outUnigramCount = traversePolicyToUpdateAllPositionFields.getUnigramCount(); + *outBigramCount = traversePolicyToUpdateAllPositionFields.getBigramCount(); + return true; +} + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h new file mode 100644 index 000000000..7223dea8b --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_writing_helper.h @@ -0,0 +1,85 @@ +/* + * 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_WRITING_HELPER_H +#define LATINIME_DYNAMIC_PATRICIA_TRIE_WRITING_HELPER_H + +#include <stdint.h> + +#include "defines.h" +#include "utils/hash_map_compat.h" + +namespace latinime { + +class BufferWithExtendableBuffer; +class DynamicBigramListPolicy; +class DynamicPatriciaTrieReadingHelper; +class DynamicShortcutListPolicy; +class HeaderPolicy; +class PtNodeReader; +class PtNodeWriter; + +// TODO: Make it independent from a particular format and move to pt_common. +class DynamicPatriciaTrieWritingHelper { + public: + typedef hash_map_compat<int, int> PtNodeArrayPositionRelocationMap; + typedef hash_map_compat<int, int> PtNodePositionRelocationMap; + struct DictPositionRelocationMap { + public: + DictPositionRelocationMap() + : mPtNodeArrayPositionRelocationMap(), mPtNodePositionRelocationMap() {} + + PtNodeArrayPositionRelocationMap mPtNodeArrayPositionRelocationMap; + PtNodePositionRelocationMap mPtNodePositionRelocationMap; + + private: + DISALLOW_COPY_AND_ASSIGN(DictPositionRelocationMap); + }; + + static const size_t MAX_DICTIONARY_SIZE; + + DynamicPatriciaTrieWritingHelper(BufferWithExtendableBuffer *const buffer, + const PtNodeReader *const ptNodeReader, PtNodeWriter *const ptNodeWriter, + DynamicBigramListPolicy *const bigramPolicy, + DynamicShortcutListPolicy *const shortcutPolicy, const bool needsToDecay) + : mBuffer(buffer), mPtNodeReader(ptNodeReader), mPtNodeWriter(ptNodeWriter), + mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy), + mNeedsToDecay(needsToDecay) {} + + ~DynamicPatriciaTrieWritingHelper() {} + + void writeToDictFile(const char *const fileName, const HeaderPolicy *const headerPolicy, + const int unigramCount, const int bigramCount); + + void writeToDictFileWithGC(const int rootPtNodeArrayPos, const char *const fileName, + const HeaderPolicy *const headerPolicy); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPatriciaTrieWritingHelper); + + BufferWithExtendableBuffer *const mBuffer; + const PtNodeReader *const mPtNodeReader; + PtNodeWriter *const mPtNodeWriter; + DynamicBigramListPolicy *const mBigramPolicy; + DynamicShortcutListPolicy *const mShortcutPolicy; + const bool mNeedsToDecay; + + bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy, + BufferWithExtendableBuffer *const bufferToWrite, int *const outUnigramCount, + int *const outBigramCount); +}; +} // namespace latinime +#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_WRITING_HELPER_H */ 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/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp new file mode 100644 index 000000000..999460086 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp @@ -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. + */ + +#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h" + +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" + +namespace latinime { + +void BigramDictContent::getBigramEntryAndAdvancePosition(int *const outProbability, + bool *const outHasNext, int *const outTargetTerminalId, int *const bigramEntryPos) const { + const BufferWithExtendableBuffer *const bigramListBuffer = getContentBuffer(); + const int bigramFlags = bigramListBuffer->readUintAndAdvancePosition( + Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos); + if (outProbability) { + *outProbability = bigramFlags & Ver4DictConstants::BIGRAM_PROBABILITY_MASK; + } + if (outHasNext) { + *outHasNext = (bigramFlags & Ver4DictConstants::BIGRAM_HAS_NEXT_MASK) != 0; + } + const int targetTerminalId = bigramListBuffer->readUintAndAdvancePosition( + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, bigramEntryPos); + if (outTargetTerminalId) { + *outTargetTerminalId = + (targetTerminalId == Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID) ? + Ver4DictConstants::NOT_A_TERMINAL_ID : targetTerminalId; + } +} + +bool BigramDictContent::writeBigramEntryAndAdvancePosition(const int probability, const int hasNext, + const int targetTerminalId, int *const entryWritingPos) { + BufferWithExtendableBuffer *const bigramListBuffer = getWritableContentBuffer(); + const int bigramFlags = createAndGetBigramFlags(probability, hasNext); + if (!bigramListBuffer->writeUintAndAdvancePosition(bigramFlags, + Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, entryWritingPos)) { + return false; + } + const int targetTerminalIdToWrite = + (targetTerminalId == Ver4DictConstants::NOT_A_TERMINAL_ID) ? + Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID : targetTerminalId; + return bigramListBuffer->writeUintAndAdvancePosition(targetTerminalIdToWrite, + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, entryWritingPos); +} + +bool BigramDictContent::copyBigramList(const int bigramListPos, const int toPos) { + bool hasNext = true; + int readingPos = bigramListPos; + int writingPos = toPos; + while(hasNext) { + int probability = NOT_A_PROBABILITY; + int targetTerminalId = Ver4DictConstants::NOT_A_TERMINAL_ID; + getBigramEntryAndAdvancePosition(&probability, &hasNext, &targetTerminalId, + &readingPos); + if (!writeBigramEntryAndAdvancePosition(probability, hasNext, targetTerminalId, + &writingPos)) { + return false; + } + } + return true; +} + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h new file mode 100644 index 000000000..c5410b83f --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h @@ -0,0 +1,77 @@ +/* + * 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_BIGRAM_DICT_CONTENT_H +#define LATINIME_BIGRAM_DICT_CONTENT_H + +#include "defines.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" + +namespace latinime { + +class BigramDictContent : public SparseTableDictContent { + public: + BigramDictContent(const char *const dictDirPath, const bool isUpdatable) + : SparseTableDictContent(dictDirPath, + Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION, + Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION, + Ver4DictConstants::BIGRAM_FILE_EXTENSION, isUpdatable, + Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, + Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE) {} + + BigramDictContent() + : SparseTableDictContent(Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, + Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE) {} + + void getBigramEntryAndAdvancePosition(int *const outProbability, bool *const outHasNext, + int *const outTargetTerminalId, int *const bigramEntryPos) const; + + // Returns head position of bigram list for a PtNode specified by terminalId. + int getBigramListHeadPos(const int terminalId) const { + const SparseTable *const addressLookupTable = getAddressLookupTable(); + if (!addressLookupTable->contains(terminalId)) { + return NOT_A_DICT_POS; + } + return addressLookupTable->get(terminalId); + } + + bool writeBigramEntryAndAdvancePosition(const int probability, const int hasNext, + const int targetTerminalId, int *const entryWritingPos); + + bool createNewBigramList(const int terminalId) { + const int bigramListPos = getContentBuffer()->getTailPosition(); + return getUpdatableAddressLookupTable()->set(terminalId, bigramListPos); + } + + bool copyBigramList(const int bigramListPos, const int toPos); + + bool flushToFile(const char *const dictDirPath) const { + return flush(dictDirPath, Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION, + Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION, + Ver4DictConstants::BIGRAM_FILE_EXTENSION); + } + + private: + DISALLOW_COPY_AND_ASSIGN(BigramDictContent); + + int createAndGetBigramFlags(const int probability, const bool hasNext) const { + return (probability & Ver4DictConstants::BIGRAM_PROBABILITY_MASK) + | (hasNext ? Ver4DictConstants::BIGRAM_HAS_NEXT_MASK : 0); + } +}; +} // namespace latinime +#endif /* LATINIME_BIGRAM_DICT_CONTENT_H */ 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/probability_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.h new file mode 100644 index 000000000..518376426 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.h @@ -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. + */ + +#ifndef LATINIME_PROBABILITY_DICT_CONTENT_H +#define LATINIME_PROBABILITY_DICT_CONTENT_H + +#include "defines.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" + +namespace latinime { + +class ProbabilityDictContent : public SingleDictContent { + public: + ProbabilityDictContent(const char *const dictDirPath, const bool isUpdatable) + : SingleDictContent(dictDirPath, Ver4DictConstants::FREQ_FILE_EXTENSION, + isUpdatable) {} + + ProbabilityDictContent() {} + + int getProbability(const int terminalId) const { + if (terminalId < 0 || terminalId >= getSize()) { + return NOT_A_PROBABILITY; + } + return Ver4PatriciaTrieReadingUtils::getProbability(getBuffer(), terminalId); + } + + bool setProbability(const int terminalId, const int probability) { + if (terminalId < 0 || terminalId > getSize()) { + return false; + } + if (terminalId == getSize()) { + // Write new entry. + int flagWritingPos = terminalId * (Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE + + Ver4DictConstants::PROBABILITY_SIZE); + const int dummyFlags = 0; + // Write dummy flags. + if (!getWritableBuffer()->writeUintAndAdvancePosition(dummyFlags, + Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE, &flagWritingPos)) { + return false; + } + } + int probabilityWritingPos = terminalId * (Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE + + Ver4DictConstants::PROBABILITY_SIZE) + + Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE; + return getWritableBuffer()->writeUintAndAdvancePosition(probability, + Ver4DictConstants::PROBABILITY_SIZE, &probabilityWritingPos); + } + + bool flushToFile(const char *const dictDirPath) const { + return flush(dictDirPath, Ver4DictConstants::FREQ_FILE_EXTENSION); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ProbabilityDictContent); + + int getSize() const { + return getBuffer()->getTailPosition() / (Ver4DictConstants::PROBABILITY_SIZE + + Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE); + } +}; +} // namespace latinime +#endif /* LATINIME_PROBABILITY_DICT_CONTENT_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h new file mode 100644 index 000000000..b11e23338 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h @@ -0,0 +1,73 @@ +/* + * 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_SHORTCUT_DICT_CONTENT_H +#define LATINIME_SHORTCUT_DICT_CONTENT_H + +#include "defines.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" + +namespace latinime { + +class ShortcutDictContent : public SparseTableDictContent { + public: + ShortcutDictContent(const char *const dictDirPath, const bool isUpdatable) + : SparseTableDictContent(dictDirPath, + Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION, + Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION, + Ver4DictConstants::SHORTCUT_FILE_EXTENSION, isUpdatable, + Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, + Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {} + + ShortcutDictContent() + : SparseTableDictContent(Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE, + Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {} + + void getShortcutEntryAndAdvancePosition(const int maxCodePointCount, + int *const outCodePoint, int *const outCodePointCount, int *const outShortcutFlags, + int *const shortcutEntryPos) const { + const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer(); + if (outShortcutFlags) { + *outShortcutFlags = shortcutListBuffer->readUintAndAdvancePosition( + Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos); + } + if (outCodePoint && outCodePointCount) { + shortcutListBuffer->readCodePointsAndAdvancePosition( + maxCodePointCount, outCodePoint, outCodePointCount, shortcutEntryPos); + } + } + + // Returns head position of shortcut list for a PtNode specified by terminalId. + int getShortcutListHeadPos(const int terminalId) const { + const SparseTable *const addressLookupTable = getAddressLookupTable(); + if (!addressLookupTable->contains(terminalId)) { + return NOT_A_DICT_POS; + } + return addressLookupTable->get(terminalId); + } + + bool flushToFile(const char *const dictDirPath) const { + return flush(dictDirPath, Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION, + Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION, + Ver4DictConstants::SHORTCUT_FILE_EXTENSION); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ShortcutDictContent); +}; +} // namespace latinime +#endif /* LATINIME_SHORTCUT_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..08780998e --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h @@ -0,0 +1,72 @@ +/* + * 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/structure/v4/ver4_dict_constants.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" +#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.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), + mIsValid(mMmappedBuffer.get() != 0) {} + + SingleDictContent() + : mMmappedBuffer(0), mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), + mIsValid(true) {} + + virtual ~SingleDictContent() {} + + virtual bool isValid() const { + return mIsValid; + } + + protected: + BufferWithExtendableBuffer *getWritableBuffer() { + return &mExpandableContentBuffer; + } + + const BufferWithExtendableBuffer *getBuffer() const { + return &mExpandableContentBuffer; + } + + bool flush(const char *const dictDirPath, const char *const contentFileName) const { + const BufferWithExtendableBuffer *bufferPtr = &mExpandableContentBuffer; + return DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, contentFileName, + &bufferPtr, 1 /* bufferCount */); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SingleDictContent); + + const MmappedBuffer::MmappedBufferPtr mMmappedBuffer; + BufferWithExtendableBuffer mExpandableContentBuffer; + const bool mIsValid; +}; +} // namespace latinime +#endif /* LATINIME_SINGLE_DICT_CONTENT_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp new file mode 100644 index 000000000..c65420614 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp @@ -0,0 +1,42 @@ +/* + * 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/content/sparse_table_dict_content.h" + +namespace latinime { + +bool SparseTableDictContent::flush(const char *const dictDirPath, + const char *const lookupTableFileName, const char *const addressTableFileName, + const char *const contentFileName) const { + const BufferWithExtendableBuffer *lookupTableBufferPtr = &mExpandableLookupTableBuffer; + if (!DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, lookupTableFileName, + &lookupTableBufferPtr, 1 /* bufferCount */)) { + return false; + } + const BufferWithExtendableBuffer *addressTableBufferPtr = &mExpandableAddressTableBuffer; + if (!DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, addressTableFileName, + &addressTableBufferPtr, 1 /* bufferCount */)) { + return false; + } + const BufferWithExtendableBuffer *contentBufferPtr = &mExpandableContentBuffer; + if (!DictFileWritingUtils::flushBuffersToFileInDir(dictDirPath, contentFileName, + &contentBufferPtr, 1 /* bufferCount */)) { + return false; + } + return true; +} + +} // namespace latinime 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..bcfecdbfb --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h @@ -0,0 +1,105 @@ +/* + * 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/structure/v4/ver4_dict_constants.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" +#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h" +#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h" +#include "suggest/policyimpl/dictionary/utils/sparse_table.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, + const int sparseTableBlockSize, const int sparseTableDataSize) + : 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), + mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer, + sparseTableBlockSize, sparseTableDataSize), + mIsValid(mLookupTableBuffer.get() != 0 && mAddressTableBuffer.get() != 0 + && mContentBuffer.get() != 0) {} + + SparseTableDictContent(const int sparseTableBlockSize, const int sparseTableDataSize) + : mLookupTableBuffer(0), mAddressTableBuffer(0), mContentBuffer(0), + mExpandableLookupTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), + mExpandableAddressTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), + mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), + mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer, + sparseTableBlockSize, sparseTableDataSize), mIsValid(true) {} + + virtual ~SparseTableDictContent() {} + + virtual bool isValid() const { + return mIsValid; + } + + protected: + SparseTable *getUpdatableAddressLookupTable() { + return &mAddressLookupTable; + } + + const SparseTable *getAddressLookupTable() const { + return &mAddressLookupTable; + } + + BufferWithExtendableBuffer *getWritableContentBuffer() { + return &mExpandableContentBuffer; + } + + const BufferWithExtendableBuffer *getContentBuffer() const { + return &mExpandableContentBuffer; + } + + bool flush(const char *const dictDirPath, const char *const lookupTableFileName, + const char *const addressTableFileName, const char *const contentFileName) const; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTableDictContent); + + const MmappedBuffer::MmappedBufferPtr mLookupTableBuffer; + const MmappedBuffer::MmappedBufferPtr mAddressTableBuffer; + const MmappedBuffer::MmappedBufferPtr mContentBuffer; + BufferWithExtendableBuffer mExpandableLookupTableBuffer; + BufferWithExtendableBuffer mExpandableAddressTableBuffer; + BufferWithExtendableBuffer mExpandableContentBuffer; + SparseTable mAddressLookupTable; + const bool mIsValid; +}; +} // namespace latinime +#endif /* LATINIME_SPARSE_TABLE_DICT_CONTENT_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h new file mode 100644 index 000000000..eaf18b56a --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h @@ -0,0 +1,81 @@ +/* + * 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_TERMINAL_POSITION_LOOKUP_TABLE_H +#define LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H + +#include <stdint.h> + +#include "defines.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" + +namespace latinime { + +class TerminalPositionLookupTable : public SingleDictContent { + public: + // TODO: Quit using headerRegionSize. + TerminalPositionLookupTable(const char *const dictDirPath, const bool isUpdatable, + const int headerRegionSize) + : SingleDictContent(dictDirPath, + Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION, isUpdatable), + mSize(getBuffer()->getTailPosition() + / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE), + mHeaderRegionSize(headerRegionSize) {} + + TerminalPositionLookupTable() : mSize(0), mHeaderRegionSize(0) {} + + int getTerminalPtNodePosition(const int terminalId) const { + if (terminalId < 0 || terminalId >= mSize) { + return NOT_A_DICT_POS; + } + const int readingPos = terminalId * Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE; + return getBuffer()->readUint(Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, + readingPos) - mHeaderRegionSize; + } + + bool setTerminalPtNodePosition(const int terminalId, const int terminalPtNodePos) { + if (terminalId < 0 || terminalId > mSize) { + return NOT_A_DICT_POS; + } + if (terminalId == mSize) { + // Use new terminal id. + mSize += 1; + } + int writingPos = terminalId * Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE; + return getWritableBuffer()->writeUintAndAdvancePosition( + terminalPtNodePos + mHeaderRegionSize, + Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, &writingPos); + } + + int getNextTerminalId() const { + return mSize; + } + + bool flushToFile(const char *const dictDirPath) const { + return flush(dictDirPath, Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TerminalPositionLookupTable); + + int mSize; + const int mHeaderRegionSize; +}; +} // namespace latinime +#endif // LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp new file mode 100644 index 000000000..e17c5eab4 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp @@ -0,0 +1,81 @@ +/* + * 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_buffers.h" + +#include <cerrno> +#include <sys/stat.h> +#include <sys/types.h> + +#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h" +#include "suggest/policyimpl/dictionary/utils/file_utils.h" + +namespace latinime { + +bool Ver4DictBuffers::flush(const char *const dictDirPath) const { + // Create temporary directory. + const int tmpDirPathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictDirPath, + DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE); + char tmpDirPath[tmpDirPathBufSize]; + FileUtils::getFilePathWithSuffix(dictDirPath, + DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE, tmpDirPathBufSize, + tmpDirPath); + if (mkdir(tmpDirPath, S_IRWXU) == -1) { + AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno); + return false; + } + // Write trie file. + const BufferWithExtendableBuffer *buffers[] = + {&mExpandableHeaderBuffer, &mExpandableTrieBuffer}; + if (!DictFileWritingUtils::flushBuffersToFileInDir(tmpDirPath, + Ver4DictConstants::TRIE_FILE_EXTENSION, buffers, 2 /* bufferCount */)) { + AKLOGE("Dictionary trie file %s/%s cannot be written.", tmpDirPath, + Ver4DictConstants::TRIE_FILE_EXTENSION); + return false; + } + // Write dictionary contents. + if (!mTerminalPositionLookupTable.flushToFile(tmpDirPath)) { + AKLOGE("Terminal position lookup table cannot be written. %s", tmpDirPath); + return false; + } + if (!mProbabilityDictContent.flushToFile(tmpDirPath)) { + AKLOGE("Probability dict content cannot be written. %s", tmpDirPath); + return false; + } + if (!mBigramDictContent.flushToFile(tmpDirPath)) { + AKLOGE("Bigram dict content cannot be written. %s", tmpDirPath); + return false; + } + if (!mShortcutDictContent.flushToFile(tmpDirPath)) { + AKLOGE("Shortcut dict content cannot be written. %s", tmpDirPath); + return false; + } + // Remove existing dictionary. + if (!FileUtils::removeDirAndFiles(dictDirPath)) { + AKLOGE("Existing directory %s cannot be removed.", dictDirPath); + ASSERT(false); + return false; + } + // Rename temporary directory. + if (rename(tmpDirPath, dictDirPath) != 0) { + AKLOGE("%s cannot be renamed to %s", tmpDirPath, dictDirPath); + ASSERT(false); + return false; + } + return true; +} + +} // namespace latinime 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..0684bdd0c --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h @@ -0,0 +1,131 @@ +/* + * 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/header/header_read_write_utils.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h" +#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.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 AK_FORCE_INLINE 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)); + } + + static AK_FORCE_INLINE Ver4DictBuffersPtr createVer4DictBuffers() { + return Ver4DictBuffersPtr(new Ver4DictBuffers()); + } + + AK_FORCE_INLINE bool isValid() const { + return mDictBuffer.get() != 0 && mProbabilityDictContent.isValid() + && mTerminalPositionLookupTable.isValid() && mBigramDictContent.isValid() + && mShortcutDictContent.isValid(); + } + + AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableHeaderBuffer() { + return &mExpandableHeaderBuffer; + } + + AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableTrieBuffer() { + return &mExpandableTrieBuffer; + } + + AK_FORCE_INLINE TerminalPositionLookupTable *getUpdatableTerminalPositionLookupTable() { + return &mTerminalPositionLookupTable; + } + + AK_FORCE_INLINE const TerminalPositionLookupTable *getTerminalPositionLookupTable() const { + return &mTerminalPositionLookupTable; + } + + AK_FORCE_INLINE ProbabilityDictContent *getUpdatableProbabilityDictContent() { + return &mProbabilityDictContent; + } + + AK_FORCE_INLINE const ProbabilityDictContent *getProbabilityDictContent() const { + return &mProbabilityDictContent; + } + + AK_FORCE_INLINE BigramDictContent *getUpdatableBigramDictContent() { + return &mBigramDictContent; + } + + AK_FORCE_INLINE const BigramDictContent *getBigramDictContent() const { + return &mBigramDictContent; + } + + AK_FORCE_INLINE const ShortcutDictContent *getShortcutDictContent() const { + return &mShortcutDictContent; + } + + AK_FORCE_INLINE bool isUpdatable() const { + return mIsUpdatable; + } + + bool flush(const char *const dictDirPath) const; + + private: + DISALLOW_COPY_AND_ASSIGN(Ver4DictBuffers); + + AK_FORCE_INLINE Ver4DictBuffers(const char *const dictDirPath, + const MmappedBuffer::MmappedBufferPtr &dictBuffer, const bool isUpdatable) + : mDictBuffer(dictBuffer), + mHeaderSize(HeaderReadWriteUtils::getHeaderSize(mDictBuffer.get()->getBuffer())), + mExpandableHeaderBuffer(dictBuffer.get()->getBuffer(), mHeaderSize, + BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), + mExpandableTrieBuffer(dictBuffer.get()->getBuffer() + mHeaderSize, + dictBuffer.get()->getBufferSize() - mHeaderSize, + BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE), + // TODO: Quit using header size. + mTerminalPositionLookupTable(dictDirPath, isUpdatable, mHeaderSize), + mProbabilityDictContent(dictDirPath, isUpdatable), + mBigramDictContent(dictDirPath, isUpdatable), + mShortcutDictContent(dictDirPath, isUpdatable), + mIsUpdatable(isUpdatable) {} + + AK_FORCE_INLINE Ver4DictBuffers() + : mDictBuffer(0), mHeaderSize(0), + mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), + mExpandableTrieBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), + mTerminalPositionLookupTable(), mProbabilityDictContent(), + mBigramDictContent(), mShortcutDictContent(), mIsUpdatable(true) {} + + const MmappedBuffer::MmappedBufferPtr mDictBuffer; + const int mHeaderSize; + BufferWithExtendableBuffer mExpandableHeaderBuffer; + BufferWithExtendableBuffer mExpandableTrieBuffer; + TerminalPositionLookupTable mTerminalPositionLookupTable; + ProbabilityDictContent mProbabilityDictContent; + BigramDictContent mBigramDictContent; + ShortcutDictContent mShortcutDictContent; + const int mIsUpdatable; +}; +} // 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..af13a374a --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp @@ -0,0 +1,59 @@ +/* + * 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"; + +// Version 4 dictionary size is implicitly limited to 8MB due to 3-byte offsets. +// TODO: Make MAX_DICTIONARY_SIZE 8MB. +const int Ver4DictConstants::MAX_DICTIONARY_SIZE = 2 * 1024 * 1024; + +const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1; +const int Ver4DictConstants::PROBABILITY_SIZE = 1; +const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1; +const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3; +const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4; + +const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 4; +const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE = 4; +const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 16; +const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE = 4; + +const int Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE = 3; +// Unsigned int max value of BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE-byte is used for representing +// invalid terminal ID in bigram lists. +const int Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID = + (1 << (BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE * 8)) - 1; +const int Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE = 1; +const int Ver4DictConstants::BIGRAM_PROBABILITY_MASK = 0x0F; +const int Ver4DictConstants::BIGRAM_HAS_NEXT_MASK = 0x80; + +const int Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE = 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..cfb7740be --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.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_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 MAX_DICTIONARY_SIZE; + + static const int NOT_A_TERMINAL_ID; + static const int PROBABILITY_SIZE; + static const int FLAGS_IN_PROBABILITY_FILE_SIZE; + static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE; + static const int TERMINAL_ID_FIELD_SIZE; + + static const int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE; + static const int BIGRAM_ADDRESS_TABLE_DATA_SIZE; + static const int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE; + static const int SHORTCUT_ADDRESS_TABLE_DATA_SIZE; + + static const int BIGRAM_FLAGS_FIELD_SIZE; + static const int BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE; + static const int INVALID_BIGRAM_TARGET_TERMINAL_ID; + static const int BIGRAM_PROBABILITY_MASK; + static const int BIGRAM_HAS_NEXT_MASK; + + static const int SHORTCUT_FLAGS_FIELD_SIZE; + + 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_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp new file mode 100644 index 000000000..b18bdc943 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp @@ -0,0 +1,95 @@ +/* + * 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_node_reader.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/content/probability_dict_content.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" + +namespace latinime { + +const PtNodeParams Ver4PatriciaTrieNodeReader::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 terminalIdFieldPos = NOT_A_DICT_POS; + int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID; + int probability = NOT_A_PROBABILITY; + if (PatriciaTrieReadingUtils::isTerminal(flags)) { + terminalIdFieldPos = pos; + if (usesAdditionalBuffer) { + terminalIdFieldPos += mBuffer->getOriginalBufferSize(); + } + terminalId = Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(dictBuf, &pos); + probability = mProbabilityDictContent->getProbability(terminalId); + } + 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(); + } + // Sibling position is the tail position of original PtNode. + int newSiblingNodePos = (siblingNodePos == NOT_A_DICT_POS) ? pos : siblingNodePos; + // 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, + terminalIdFieldPos, terminalId, probability, childrenPosFieldPos, childrenPos, + newBigramLinkedNodePos, newSiblingNodePos); + } +} + +} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h new file mode 100644 index 000000000..bdae0de7e --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h @@ -0,0 +1,58 @@ +/* + * 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_NODE_READER_H +#define LATINIME_VER4_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 ProbabilityDictContent; + +/* + * This class is used for helping to read nodes of ver4 patricia trie. This class handles moved + * node and reads node attributes including probability form probabilityBuffer. + */ +class Ver4PatriciaTrieNodeReader : public PtNodeReader { + public: + Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer, + const ProbabilityDictContent *const probabilityDictContent) + : mBuffer(buffer), mProbabilityDictContent(probabilityDictContent) {} + + ~Ver4PatriciaTrieNodeReader() {} + + 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(Ver4PatriciaTrieNodeReader); + + const BufferWithExtendableBuffer *const mBuffer; + const ProbabilityDictContent *const mProbabilityDictContent; + + const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos, + const int siblingNodePos, const int bigramLinkedNodePos) const; +}; +} // namespace latinime +#endif /* LATINIME_VER4_PATRICIA_TRIE_NODE_READER_H */ diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp new file mode 100644 index 000000000..b572ee87f --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp @@ -0,0 +1,199 @@ +/* + * 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_node_writer.h" + +#include "suggest/policyimpl/dictionary/bigram/ver4_bigram_list_policy.h" +#include "suggest/policyimpl/dictionary/shortcut/dynamic_shortcut_list_policy.h" +#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_reading_utils.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.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/structure/v4/ver4_dict_buffers.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" + +namespace latinime { + +const int Ver4PatriciaTrieNodeWriter::CHILDREN_POSITION_FIELD_SIZE = 3; + +bool Ver4PatriciaTrieNodeWriter::markPtNodeAsDeleted( + const PtNodeParams *const toBeUpdatedPtNodeParams) { + int pos = toBeUpdatedPtNodeParams->getHeadPos(); + const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos); + const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer); + if (usesAdditionalBuffer) { + pos -= mTrieBuffer->getOriginalBufferSize(); + } + // Read original flags + const PatriciaTrieReadingUtils::NodeFlags originalFlags = + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos); + const PatriciaTrieReadingUtils::NodeFlags updatedFlags = + DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */, + true /* isDeleted */); + int writingPos = toBeUpdatedPtNodeParams->getHeadPos(); + // Update flags. + return DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags, + &writingPos); +} + +bool Ver4PatriciaTrieNodeWriter::markPtNodeAsMoved( + const PtNodeParams *const toBeUpdatedPtNodeParams, + const int movedPos, const int bigramLinkedNodePos) { + int pos = toBeUpdatedPtNodeParams->getHeadPos(); + const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos); + const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer); + if (usesAdditionalBuffer) { + pos -= mTrieBuffer->getOriginalBufferSize(); + } + // Read original flags + const PatriciaTrieReadingUtils::NodeFlags originalFlags = + PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos); + const PatriciaTrieReadingUtils::NodeFlags updatedFlags = + DynamicPatriciaTrieReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */, + false /* isDeleted */); + int writingPos = toBeUpdatedPtNodeParams->getHeadPos(); + // Update flags. + if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags, + &writingPos)) { + return false; + } + // Update moved position, which is stored in the parent offset field. + if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition( + mTrieBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) { + return false; + } + // Update bigram linked node position, which is stored in the children position field. + int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos(); + if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition( + mTrieBuffer, bigramLinkedNodePos, &childrenPosFieldPos)) { + return false; + } + if (toBeUpdatedPtNodeParams->hasChildren()) { + // Update children's parent position. + mReadingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos()); + while (!mReadingHelper.isEnd()) { + const PtNodeParams childPtNodeParams(mReadingHelper.getPtNodeParams()); + int parentOffsetFieldPos = childPtNodeParams.getHeadPos() + + DynamicPatriciaTrieWritingUtils::NODE_FLAG_FIELD_SIZE; + if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition( + mTrieBuffer, 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; + } + mReadingHelper.readNextSiblingNode(childPtNodeParams); + } + } + return true; +} + +bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbability( + const PtNodeParams *const toBeUpdatedPtNodeParams, const int newProbability) { + if (!toBeUpdatedPtNodeParams->isTerminal()) { + return false; + } + return mBuffers->getUpdatableProbabilityDictContent()->setProbability( + toBeUpdatedPtNodeParams->getTerminalId(), newProbability); +} + +bool Ver4PatriciaTrieNodeWriter::updateChildrenPosition( + const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) { + int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos(); + return DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer, + newChildrenPosition, &childrenPosFieldPos); +} + +bool Ver4PatriciaTrieNodeWriter::writePtNodeAndAdvancePosition( + const PtNodeParams *const ptNodeParams, int *const ptNodeWritingPos) { + const int nodePos = *ptNodeWritingPos; + // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the + // PtNode writing. + if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, + 0 /* nodeFlags */, ptNodeWritingPos)) { + return false; + } + // Calculate a parent offset and write the offset. + if (!DynamicPatriciaTrieWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer, + ptNodeParams->getParentPos(), nodePos, ptNodeWritingPos)) { + return false; + } + // Write code points + if (!DynamicPatriciaTrieWritingUtils::writeCodePointsAndAdvancePosition(mTrieBuffer, + ptNodeParams->getCodePoints(), ptNodeParams->getCodePointCount(), ptNodeWritingPos)) { + return false; + } + int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID; + if (ptNodeParams->getTerminalId() != Ver4DictConstants::NOT_A_TERMINAL_ID) { + terminalId = ptNodeParams->getTerminalId(); + } else if (ptNodeParams->getProbability() != NOT_A_PROBABILITY) { + // Write terminal information using a new terminal id. + // Get a new unused terminal id. + terminalId = mBuffers->getTerminalPositionLookupTable()->getNextTerminalId(); + } + const int isTerminal = terminalId != Ver4DictConstants::NOT_A_TERMINAL_ID; + if (isTerminal) { + // Update the lookup table. + if (!mBuffers->getUpdatableTerminalPositionLookupTable()->setTerminalPtNodePosition( + terminalId, nodePos)) { + return false; + } + // Write terminal Id. + if (!mTrieBuffer->writeUintAndAdvancePosition(terminalId, + Ver4DictConstants::TERMINAL_ID_FIELD_SIZE, ptNodeWritingPos)) { + return false; + } + // Write probability. + if (!mBuffers->getUpdatableProbabilityDictContent()->setProbability( + terminalId, ptNodeParams->getProbability())) { + return false; + } + } + // Write children position + if (!DynamicPatriciaTrieWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer, + ptNodeParams->getChildrenPos(), ptNodeWritingPos)) { + return false; + } + // Create node flags and write them. + PatriciaTrieReadingUtils::NodeFlags nodeFlags = + PatriciaTrieReadingUtils::createAndGetFlags(ptNodeParams->isBlacklisted(), + ptNodeParams->isNotAWord(), isTerminal, + false /* hasShortcutTargets */, false /* hasBigrams */, + ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */, + CHILDREN_POSITION_FIELD_SIZE); + int flagsFieldPos = nodePos; + if (!DynamicPatriciaTrieWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, nodeFlags, + &flagsFieldPos)) { + return false; + } + return true; +} + +bool Ver4PatriciaTrieNodeWriter::addNewBigramEntry( + const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam, const int probability, + bool *const outAddedNewBigram) { + return mBigramPolicy->addNewEntry(sourcePtNodeParams->getTerminalId(), + targetPtNodeParam->getTerminalId(), probability, outAddedNewBigram); +} + +bool Ver4PatriciaTrieNodeWriter::removeBigramEntry( + const PtNodeParams *const sourcePtNodeParams, const PtNodeParams *const targetPtNodeParam) { + return mBigramPolicy->removeEntry(sourcePtNodeParams->getTerminalId(), + targetPtNodeParam->getTerminalId()); +} + +} diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h new file mode 100644 index 000000000..d11952304 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h @@ -0,0 +1,84 @@ +/* + * 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_NODE_WRITER_H +#define LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_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_writer.h" +#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_reading_helper.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h" + +namespace latinime { + +class BufferWithExtendableBuffer; +class Ver4BigramListPolicy; +class Ver4DictBuffers; +class Ver4ShortcutListPolicy; + +/* + * This class is used for helping to writes nodes of ver4 patricia trie. + */ +class Ver4PatriciaTrieNodeWriter : public PtNodeWriter { + public: + Ver4PatriciaTrieNodeWriter(BufferWithExtendableBuffer *const trieBuffer, + Ver4DictBuffers *const buffers, const Ver4PatriciaTrieNodeReader *const ptNodeReader, + Ver4BigramListPolicy *const bigramPolicy, Ver4ShortcutListPolicy *const shortcutPolicy) + : mTrieBuffer(trieBuffer), mBuffers(buffers), mPtNodeReader(ptNodeReader), + mReadingHelper(mTrieBuffer, mPtNodeReader), + mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy) {} + + virtual ~Ver4PatriciaTrieNodeWriter() {} + + virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams); + + virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int movedPos, const int bigramLinkedNodePos); + + virtual bool updatePtNodeProbability(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int newProbability); + + virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams, + const int newChildrenPosition); + + virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams, + int *const ptNodeWritingPos); + + virtual bool addNewBigramEntry(const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam, const int probability, + bool *const outAddedNewBigram); + + virtual bool removeBigramEntry(const PtNodeParams *const sourcePtNodeParams, + const PtNodeParams *const targetPtNodeParam); + + private: + DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter); + + static const int CHILDREN_POSITION_FIELD_SIZE; + + BufferWithExtendableBuffer *const mTrieBuffer; + Ver4DictBuffers *const mBuffers; + const Ver4PatriciaTrieNodeReader *const mPtNodeReader; + DynamicPatriciaTrieReadingHelper mReadingHelper; + Ver4BigramListPolicy *const mBigramPolicy; + Ver4ShortcutListPolicy *const mShortcutPolicy; + +}; +} // namespace latinime +#endif /* LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_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..698483a79 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp @@ -0,0 +1,236 @@ +/* + * 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" + +#include "suggest/core/dicnode/dic_node.h" +#include "suggest/core/dicnode/dic_node_vector.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/v4/ver4_patricia_trie_node_reader.h" +#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h" +#include "suggest/policyimpl/dictionary/utils/probability_utils.h" + +namespace latinime { + +const int Ver4PatriciaTriePolicy::MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS = 1024; +const int Ver4PatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS = + Ver4DictConstants::MAX_DICTIONARY_SIZE - MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS; + +void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode, + DicNodeVector *const childDicNodes) const { + if (!dicNode->hasChildren()) { + return; + } + DynamicPatriciaTrieReadingHelper readingHelper(mDictBuffer, &mNodeReader); + readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPtNodeArrayPos()); + while (!readingHelper.isEnd()) { + 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(ptNodeParams.getProbability(), NOT_A_PROBABILITY) + != NOT_A_PROBABILITY; + } + childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(), + ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal, + ptNodeParams.hasChildren(), + ptNodeParams.isBlacklisted() + || ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */, + ptNodeParams.getCodePointCount(), ptNodeParams.getCodePoints()); + readingHelper.readNextSiblingNode(ptNodeParams); + } +} + +int Ver4PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount( + const int ptNodePos, const int maxCodePointCount, int *const outCodePoints, + int *const outUnigramProbability) const { + DynamicPatriciaTrieReadingHelper readingHelper(mDictBuffer, &mNodeReader); + readingHelper.initWithPtNodePos(ptNodePos); + return readingHelper.getCodePointsAndProbabilityAndReturnCodePointCount( + maxCodePointCount, outCodePoints, outUnigramProbability); +} + +int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord, + const int length, const bool forceLowerCaseSearch) const { + DynamicPatriciaTrieReadingHelper readingHelper(mDictBuffer, &mNodeReader); + readingHelper.initWithPtNodeArrayPos(getRootPosition()); + return readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch); +} + +int Ver4PatriciaTriePolicy::getProbability(const int unigramProbability, + const int bigramProbability) const { + if (mHeaderPolicy.isDecayingDict()) { + // Both probabilities are encoded. Decode them and get probability. + return ForgettingCurveUtils::getProbability(unigramProbability, bigramProbability); + } else { + if (unigramProbability == NOT_A_PROBABILITY) { + return NOT_A_PROBABILITY; + } else if (bigramProbability == NOT_A_PROBABILITY) { + return ProbabilityUtils::backoff(unigramProbability); + } else { + // bigramProbability is a bigram probability delta. + return ProbabilityUtils::computeProbabilityForBigram(unigramProbability, + bigramProbability); + } + } +} + +int Ver4PatriciaTriePolicy::getUnigramProbabilityOfPtNode(const int ptNodePos) const { + if (ptNodePos == NOT_A_DICT_POS) { + return NOT_A_PROBABILITY; + } + const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos)); + if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) { + return NOT_A_PROBABILITY; + } + return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY); +} + +int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const { + if (ptNodePos == NOT_A_DICT_POS) { + return NOT_A_DICT_POS; + } + const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos)); + if (ptNodeParams.isDeleted()) { + return NOT_A_DICT_POS; + } + return mBuffers.get()->getShortcutDictContent()->getShortcutListHeadPos( + ptNodeParams.getTerminalId()); +} + +int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const { + if (ptNodePos == NOT_A_DICT_POS) { + return NOT_A_DICT_POS; + } + const PtNodeParams ptNodeParams(mNodeReader.fetchNodeInfoInBufferFromPtNodePos(ptNodePos)); + if (ptNodeParams.isDeleted()) { + return NOT_A_DICT_POS; + } + return mBuffers.get()->getBigramDictContent()->getBigramListHeadPos( + ptNodeParams.getTerminalId()); +} + +bool Ver4PatriciaTriePolicy::addUnigramWord(const int *const word, const int length, + const int probability) { + if (!mBuffers.get()->isUpdatable()) { + AKLOGI("Warning: addUnigramWord() is called for non-updatable dictionary."); + return false; + } + if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) { + AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d", + mDictBuffer->getTailPosition()); + return false; + } + DynamicPatriciaTrieReadingHelper readingHelper(mDictBuffer, &mNodeReader); + readingHelper.initWithPtNodeArrayPos(getRootPosition()); + bool addedNewUnigram = false; + if (mUpdatingHelper.addUnigramWord(&readingHelper, word, length, probability, + &addedNewUnigram)) { + if (addedNewUnigram) { + mUnigramCount++; + } + return true; + } else { + return false; + } +} + +bool Ver4PatriciaTriePolicy::addBigramWords(const int *const word0, const int length0, + const int *const word1, const int length1, const int probability) { + if (!mBuffers.get()->isUpdatable()) { + AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary."); + return false; + } + if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) { + AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d", + mDictBuffer->getTailPosition()); + return false; + } + const int word0Pos = getTerminalPtNodePositionOfWord(word0, length0, + false /* forceLowerCaseSearch */); + if (word0Pos == NOT_A_DICT_POS) { + return false; + } + const int word1Pos = getTerminalPtNodePositionOfWord(word1, length1, + false /* forceLowerCaseSearch */); + if (word1Pos == NOT_A_DICT_POS) { + return false; + } + bool addedNewBigram = false; + if (mUpdatingHelper.addBigramWords(word0Pos, word1Pos, probability, &addedNewBigram)) { + if (addedNewBigram) { + mBigramCount++; + } + return true; + } else { + return false; + } +} + +bool Ver4PatriciaTriePolicy::removeBigramWords(const int *const word0, const int length0, + const int *const word1, const int length1) { + if (!mBuffers.get()->isUpdatable()) { + AKLOGI("Warning: addBigramWords() is called for non-updatable dictionary."); + return false; + } + if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) { + AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d", + mDictBuffer->getTailPosition()); + return false; + } + const int word0Pos = getTerminalPtNodePositionOfWord(word0, length0, + false /* forceLowerCaseSearch */); + if (word0Pos == NOT_A_DICT_POS) { + return false; + } + const int word1Pos = getTerminalPtNodePositionOfWord(word1, length1, + false /* forceLowerCaseSearch */); + if (word1Pos == NOT_A_DICT_POS) { + return false; + } + if (mUpdatingHelper.removeBigramWords(word0Pos, word1Pos)) { + mBigramCount--; + return true; + } else { + 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..e8fdf5513 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h @@ -0,0 +1,127 @@ +/* + * 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/bigram/ver4_bigram_list_policy.h" +#include "suggest/policyimpl/dictionary/header/header_policy.h" +#include "suggest/policyimpl/dictionary/shortcut/ver4_shortcut_list_policy.h" +#include "suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_updating_helper.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h" +#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.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()->getWritableHeaderBuffer()->getBuffer( + false /* usesAdditionalBuffer*/), FormatUtils::VERSION_4), + mDictBuffer(mBuffers.get()->getWritableTrieBuffer()), + mBigramPolicy(mBuffers.get()->getUpdatableBigramDictContent(), + mBuffers.get()->getTerminalPositionLookupTable()), + mShortcutPolicy(mBuffers.get()->getShortcutDictContent(), + mBuffers.get()->getTerminalPositionLookupTable()), + mNodeReader(mDictBuffer, mBuffers.get()->getProbabilityDictContent()), + mNodeWriter(mDictBuffer, mBuffers.get(), &mNodeReader, &mBigramPolicy, + &mShortcutPolicy), + mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter, + mHeaderPolicy.isDecayingDict()), + mUnigramCount(mHeaderPolicy.getUnigramCount()), + mBigramCount(mHeaderPolicy.getBigramCount()) {}; + + 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 &mBigramPolicy; + } + + const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const { + return &mShortcutPolicy; + } + + 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); + + // When the dictionary size is near the maximum size, we have to refuse dynamic operations to + // prevent the dictionary from overflowing. + static const int MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS; + static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS; + + Ver4DictBuffers::Ver4DictBuffersPtr mBuffers; + const HeaderPolicy mHeaderPolicy; + BufferWithExtendableBuffer *const mDictBuffer; + Ver4BigramListPolicy mBigramPolicy; + Ver4ShortcutListPolicy mShortcutPolicy; + Ver4PatriciaTrieNodeReader mNodeReader; + Ver4PatriciaTrieNodeWriter mNodeWriter; + DynamicPatriciaTrieUpdatingHelper mUpdatingHelper; + int mUnigramCount; + int mBigramCount; +}; +} // namespace latinime +#endif // LATINIME_VER4_PATRICIA_TRIE_POLICY_H diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp new file mode 100644 index 000000000..321fd6d40 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.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/byte_array_utils.h" + +namespace latinime { + +/* static */ int Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition( + const uint8_t *const buffer, int *pos) { + return ByteArrayUtils::readUint32AndAdvancePosition(buffer, pos); +} + +/* static */ int Ver4PatriciaTrieReadingUtils::getProbability( + const BufferWithExtendableBuffer *const probabilityBuffer, const int terminalId) { + const int pos = terminalId * (Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE + + Ver4DictConstants::PROBABILITY_SIZE) + + Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE; + return probabilityBuffer->readUint(Ver4DictConstants::PROBABILITY_SIZE, pos); +} + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h new file mode 100644 index 000000000..19e6dd331 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h @@ -0,0 +1,40 @@ +/* + * 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_READING_UTILS_H +#define LATINIME_VER4_PATRICIA_TRIE_READING_UTILS_H + +#include <stdint.h> + +#include "defines.h" + +namespace latinime { + +class BufferWithExtendableBuffer; + +class Ver4PatriciaTrieReadingUtils { + public: + static int getTerminalIdAndAdvancePosition(const uint8_t *const buffer, + int *const pos); + + static int getProbability(const BufferWithExtendableBuffer *const probabilityBuffer, + const int terminalId); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieReadingUtils); +}; +} // namespace latinime +#endif /* LATINIME_VER4_PATRICIA_TRIE_READING_UTILS_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..26eafcd44 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,11 +18,42 @@ 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; +uint32_t BufferWithExtendableBuffer::readUint(const int size, const int pos) const { + const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(pos); + const int posInBuffer = readingPosIsInAdditionalBuffer ? pos - mOriginalBufferSize : pos; + return ByteArrayUtils::readUint(getBuffer(readingPosIsInAdditionalBuffer), size, posInBuffer); +} + +uint32_t BufferWithExtendableBuffer::readUintAndAdvancePosition(const int size, + int *const pos) const { + const int value = readUint(size, *pos); + *pos += size; + return value; +} + +void BufferWithExtendableBuffer::readCodePointsAndAdvancePosition(const int maxCodePointCount, + int *const outCodePoints, int *outCodePointCount, int *const pos) const { + const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(*pos); + if (readingPosIsInAdditionalBuffer) { + *pos -= mOriginalBufferSize; + } + *outCodePointCount = ByteArrayUtils::readStringAndAdvancePosition( + getBuffer(readingPosIsInAdditionalBuffer), maxCodePointCount, outCodePointCount, pos); + if (readingPosIsInAdditionalBuffer) { + *pos += mOriginalBufferSize; + } +} + +bool BufferWithExtendableBuffer::writeUint(const uint32_t data, const int size, const int pos) { + int writingPos = pos; + return writeUintAndAdvancePosition(data, size, &writingPos); +} + bool BufferWithExtendableBuffer::writeUintAndAdvancePosition(const uint32_t data, const int size, int *const pos) { if (!(size >= 1 && size <= 4)) { @@ -46,7 +77,7 @@ bool BufferWithExtendableBuffer::writeUintAndAdvancePosition(const uint32_t data } bool BufferWithExtendableBuffer::writeCodePointsAndAdvancePosition(const int *const codePoints, - const int codePointCount, const bool writesTerminator ,int *const pos) { + const int codePointCount, const bool writesTerminator, int *const pos) { const size_t size = ByteArrayUtils::calculateRequiredByteCountToStoreCodePoints( codePoints, codePointCount, writesTerminator); if (!checkAndPrepareWriting(*pos, size)) { 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..ee6107ad7 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; } @@ -63,6 +71,13 @@ class BufferWithExtendableBuffer { } } + uint32_t readUint(const int size, const int pos) const; + + uint32_t readUintAndAdvancePosition(const int size, int *const pos) const; + + void readCodePointsAndAdvancePosition(const int maxCodePointCount, + int *const outCodePoints, int *outCodePointCount, int *const pos) const; + AK_FORCE_INLINE int getOriginalBufferSize() const { return mOriginalBufferSize; } @@ -78,6 +93,8 @@ class BufferWithExtendableBuffer { * Writing is allowed for original buffer, already written region of additional buffer and the * tail of additional buffer. */ + bool writeUint(const uint32_t data, const int size, const int pos); + bool writeUintAndAdvancePosition(const uint32_t data, const int size, int *const pos); bool writeCodePointsAndAdvancePosition(const int *const codePoints, const int codePointCount, @@ -86,7 +103,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/byte_array_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h index 0c1576818..ebdd523e1 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h @@ -114,6 +114,24 @@ class ByteArrayUtils { return buffer[(*pos)++]; } + static AK_FORCE_INLINE int readUint(const uint8_t *const buffer, + const int size, const int pos) { + // size must be in 1 to 4. + ASSERT(size >= 1 && size <= 4); + switch (size) { + case 1: + return ByteArrayUtils::readUint8(buffer, pos); + case 2: + return ByteArrayUtils::readUint16(buffer, pos); + case 3: + return ByteArrayUtils::readUint24(buffer, pos); + case 4: + return ByteArrayUtils::readUint32(buffer, pos); + default: + return 0; + } + } + /** * Code Point Reading * 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..2de8a6012 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 @@ -17,11 +17,12 @@ #include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h" #include <cstdio> -#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/structure/v4/ver4_dict_buffers.h" #include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" +#include "suggest/policyimpl/dictionary/utils/file_utils.h" #include "suggest/policyimpl/dictionary/utils/format_utils.h" namespace latinime { @@ -33,57 +34,94 @@ const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE = switch (dictVersion) { case 3: return createEmptyV3DictFile(filePath, attributeMap); + case 4: + return createEmptyV4DictFile(filePath, attributeMap); default: - // Only version 3 dictionary is supported for now. + AKLOGE("Cannot create dictionary %s because format version %d is not supported.", + filePath, dictVersion); return false; } } /* 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 */)) { + AKLOGE("Empty ver3 dictionary structure cannot be created on memory."); return false; } return flushAllHeaderAndBodyToFile(filePath, &headerBuffer, &bodyBuffer); } +/* static */ bool DictFileWritingUtils::createEmptyV4DictFile(const char *const dirPath, + const HeaderReadWriteUtils::AttributeMap *const attributeMap) { + Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers = Ver4DictBuffers::createVer4DictBuffers(); + HeaderPolicy headerPolicy(FormatUtils::VERSION_4, attributeMap); + headerPolicy.writeHeaderToBuffer(dictBuffers.get()->getWritableHeaderBuffer(), + true /* updatesLastUpdatedTime */, true /* updatesLastDecayedTime */, + 0 /* unigramCount */, 0 /* bigramCount */, 0 /* extendedRegionSize */); + if (!DynamicPatriciaTrieWritingUtils::writeEmptyDictionary( + dictBuffers.get()->getWritableTrieBuffer(), 0 /* rootPos */)) { + AKLOGE("Empty ver4 dictionary structure cannot be created on memory."); + return false; + } + return dictBuffers.get()->flush(dirPath); +} + /* static */ bool DictFileWritingUtils::flushAllHeaderAndBodyToFile(const char *const filePath, BufferWithExtendableBuffer *const dictHeader, BufferWithExtendableBuffer *const dictBody) { - const int tmpFileNameBufSize = strlen(filePath) - + strlen(TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE) + 1 /* terminator */; + const int tmpFileNameBufSize = FileUtils::getFilePathWithSuffixBufSize(filePath, + TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE); // Name of a temporary file used for writing that is a connected string of original name and // TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE. char tmpFileName[tmpFileNameBufSize]; - snprintf(tmpFileName, tmpFileNameBufSize, "%s%s", filePath, - TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE); - FILE *const file = fopen(tmpFileName, "wb"); - if (!file) { - AKLOGE("Dictionary file %s cannnot be opened.", tmpFileName); - ASSERT(false); + FileUtils::getFilePathWithSuffix(filePath, TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE, + tmpFileNameBufSize, tmpFileName); + const BufferWithExtendableBuffer *buffers[] = {dictHeader, dictBody}; + if (!DictFileWritingUtils::flushBuffersToFile(tmpFileName, buffers, 2 /* bufferCount */)) { + AKLOGE("Dictionary structure cannot be written to %s.", tmpFileName); return false; } - // Write the dictionary header. - if (!writeBufferToFile(file, dictHeader)) { - remove(tmpFileName); - AKLOGE("Dictionary header cannnot be written. size: %d", dictHeader->getTailPosition()); - ASSERT(false); - return false; + if (rename(tmpFileName, filePath) != 0) { + AKLOGE("Dictionary file %s cannot be renamed to %s", tmpFileName, filePath);; } - // Write the dictionary body. - if (!writeBufferToFile(file, dictBody)) { - remove(tmpFileName); - AKLOGE("Dictionary body cannnot be written. size: %d", dictBody->getTailPosition()); + return true; +} + +/* static */ bool DictFileWritingUtils::flushBuffersToFileInDir(const char *const dirPath, + const char *const fileName, const BufferWithExtendableBuffer **const buffers, + const int bufferCount) { + const int filePathBufSize = FileUtils::getFilePathBufSize(dirPath, fileName); + char filePath[filePathBufSize]; + FileUtils::getFilePath(dirPath, fileName, filePathBufSize, filePath); + return flushBuffersToFile(filePath, buffers, bufferCount); +} + +/* static */ bool DictFileWritingUtils::flushBuffersToFile(const char *const filePath, + const BufferWithExtendableBuffer **const buffers, const int bufferCount) { + FILE *const file = fopen(filePath, "wb"); + if (!file) { + AKLOGE("File %s cannot be opened.", filePath); ASSERT(false); return false; } + for (int i = 0; i < bufferCount; ++i) { + if (!writeBufferToFile(file, buffers[i])) { + remove(filePath); + AKLOGE("Buffer cannot be written to the file %s. size: %d", filePath, + buffers[i]->getTailPosition()); + ASSERT(false); + return false; + } + } fclose(file); - rename(tmpFileName, filePath); return true; } diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h index bd4ac66fd..980a1ff4e 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h @@ -28,6 +28,8 @@ class BufferWithExtendableBuffer; class DictFileWritingUtils { public: + static const char *const TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE; + static bool createEmptyDictFile(const char *const filePath, const int dictVersion, const HeaderReadWriteUtils::AttributeMap *const attributeMap); @@ -35,14 +37,21 @@ class DictFileWritingUtils { BufferWithExtendableBuffer *const dictHeader, BufferWithExtendableBuffer *const dictBody); + static bool flushBuffersToFileInDir(const char *const dirPath, const char *const fileName, + const BufferWithExtendableBuffer **const buffers, const int bufferCount); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(DictFileWritingUtils); - static const char *const TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE; - static bool createEmptyV3DictFile(const char *const filePath, const HeaderReadWriteUtils::AttributeMap *const attributeMap); + static bool createEmptyV4DictFile(const char *const filePath, + const HeaderReadWriteUtils::AttributeMap *const attributeMap); + + static bool flushBuffersToFile(const char *const filePath, + const BufferWithExtendableBuffer **const buffers, const int bufferCount); + static bool writeBufferToFile(FILE *const file, const BufferWithExtendableBuffer *const buffer); }; diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp new file mode 100644 index 000000000..1748d5a49 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp @@ -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. + */ + +#include "suggest/policyimpl/dictionary/utils/file_utils.h" + +#include <cstdio> +#include <cstring> +#include <dirent.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +namespace latinime { + +// Returns -1 on error. +/* static */ int FileUtils::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); +} + +// Remove a directory and all files in the directory. +/* static */ bool FileUtils::removeDirAndFiles(const char *const dirPath) { + DIR *const dir = opendir(dirPath); + if (dir == NULL) { + AKLOGE("Cannot open dir %s.", dirPath); + return true; + } + struct dirent *dirent; + while ((dirent = readdir(dir)) != NULL) { + if (dirent->d_type != DT_REG) { + continue; + } + const int filePathBufSize = getFilePathBufSize(dirPath, dirent->d_name); + char filePath[filePathBufSize]; + getFilePath(dirPath, dirent->d_name, filePathBufSize, filePath); + if (remove(filePath) != 0) { + AKLOGE("Cannot remove file %s.", filePath); + return false; + } + } + if (remove(dirPath) != 0) { + AKLOGE("Cannot remove directory %s.", dirPath); + return false; + } + return true; +} + +/* static */ int FileUtils::getFilePathWithSuffixBufSize(const char *const filePath, + const char *const suffix) { + return strlen(filePath) + strlen(suffix) + 1 /* terminator */; +} + +/* static */ void FileUtils::getFilePathWithSuffix(const char *const filePath, + const char *const suffix, const int filePathBufSize, char *const outFilePath) { + snprintf(outFilePath, filePathBufSize, "%s%s", filePath, suffix); +} + +/* static */ int FileUtils::getFilePathBufSize(const char *const dirPath, + const char *const fileName) { + return strlen(dirPath) + 1 /* '/' */ + strlen(fileName) + 1 /* terminator */; +} + +/* static */ void FileUtils::getFilePath(const char *const dirPath, const char *const fileName, + const int filePathBufSize, char *const outFilePath) { + snprintf(outFilePath, filePathBufSize, "%s/%s", dirPath, fileName); +} + +} // namespace latinime 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..fc27aeecb --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.h @@ -0,0 +1,46 @@ +/* + * 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 "defines.h" + +namespace latinime { + +class FileUtils { + public: + // Returns -1 on error. + static int getFileSize(const char *const filePath); + + // Remove a directory and all files in the directory. + static bool removeDirAndFiles(const char *const dirPath); + + static int getFilePathWithSuffixBufSize(const char *const filePath, const char *const suffix); + + static void getFilePathWithSuffix(const char *const filePath, const char *const suffix, + const int filePathBufSize, char *const outFilePath); + + static int getFilePathBufSize(const char *const dirPath, const char *const fileName); + + static void getFilePath(const char *const dirPath, const char *const fileName, + const int filePathBufSize, char *const outFilePath); + + 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..e88d6e0a9 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp @@ -0,0 +1,98 @@ +/* + * 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 mmapFd = open(path, O_RDONLY); + if (mmapFd < 0) { + AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno); + return MmappedBufferPtr(0); + } + const int pagesize = sysconf(_SC_PAGESIZE); + 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/dictionary/utils/sparse_table.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.cpp new file mode 100644 index 000000000..9be35620c --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.cpp @@ -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. + */ + +#include "suggest/policyimpl/dictionary/utils/sparse_table.h" + +namespace latinime { + +const int SparseTable::NOT_EXIST = -1; +const int SparseTable::INDEX_SIZE = 4; + +bool SparseTable::contains(const int id) const { + const int readingPos = getPosInIndexTable(id); + if (id < 0 || mIndexTableBuffer->getTailPosition() <= readingPos) { + return false; + } + const int index = mIndexTableBuffer->readUint(INDEX_SIZE, readingPos); + return index != NOT_EXIST; +} + +uint32_t SparseTable::get(const int id) const { + const int indexTableReadingPos = getPosInIndexTable(id); + const int index = mIndexTableBuffer->readUint(INDEX_SIZE, indexTableReadingPos); + const int contentTableReadingPos = getPosInContentTable(id, index); + return mContentTableBuffer->readUint(mDataSize, contentTableReadingPos); +} + +bool SparseTable::set(const int id, const uint32_t value) { + const int posInIndexTable = getPosInIndexTable(id); + // Extends the index table if needed. + if (mIndexTableBuffer->getTailPosition() < posInIndexTable) { + int tailPos = mIndexTableBuffer->getTailPosition(); + while(tailPos < posInIndexTable) { + if (!mIndexTableBuffer->writeUintAndAdvancePosition(NOT_EXIST, INDEX_SIZE, &tailPos)) { + return false; + } + } + } + if (contains(id)) { + // The entry is already in the content table. + const int index = mIndexTableBuffer->readUint(INDEX_SIZE, posInIndexTable); + return mContentTableBuffer->writeUint(value, mDataSize, getPosInContentTable(id, index)); + } + // The entry is not in the content table. + // Create new entry in the content table. + const int index = getIndexFromContentTablePos(mContentTableBuffer->getTailPosition()); + if (!mIndexTableBuffer->writeUint(index, INDEX_SIZE, posInIndexTable)) { + return false; + } + // Write a new block that containing the entry to be set. + int writingPos = getPosInContentTable(0 /* id */, index); + for (int i = 0; i < mBlockSize; ++i) { + if (!mContentTableBuffer->writeUintAndAdvancePosition(NOT_A_DICT_POS, mDataSize, + &writingPos)) { + return false; + } + } + return mContentTableBuffer->writeUint(value, mDataSize, getPosInContentTable(id, index)); +} + +int SparseTable::getIndexFromContentTablePos(const int contentTablePos) const { + return contentTablePos / mDataSize / mBlockSize; +} + +int SparseTable::getPosInIndexTable(const int id) const { + return (id / mBlockSize) * INDEX_SIZE; +} + +int SparseTable::getPosInContentTable(const int id, const int index) const { + const int offset = id % mBlockSize; + return (index * mDataSize + offset) * mBlockSize; +} + +} // namespace latinime diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.h b/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.h new file mode 100644 index 000000000..21c167506 --- /dev/null +++ b/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LATINIME_SPARSE_TABLE_H +#define LATINIME_SPARSE_TABLE_H + +#include <stdint.h> + +#include "defines.h" +#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h" + +namespace latinime { + +// Note that there is a corresponding implementation in SparseTable.java. +// TODO: Support multiple content buffers. +class SparseTable { + public: + SparseTable(BufferWithExtendableBuffer *const indexTableBuffer, + BufferWithExtendableBuffer *const contentTableBuffer, const int blockSize, + const int dataSize) + : mIndexTableBuffer(indexTableBuffer), mContentTableBuffer(contentTableBuffer), + mBlockSize(blockSize), mDataSize(dataSize) {} + + bool contains(const int id) const; + + uint32_t get(const int id) const; + + bool set(const int id, const uint32_t value); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTable); + + int getIndexFromContentTablePos(const int contentTablePos) const; + + int getPosInIndexTable(const int id) const; + + int getPosInContentTable(const int id, const int index) const; + + static const int NOT_EXIST; + static const int INDEX_SIZE; + + BufferWithExtendableBuffer *const mIndexTableBuffer; + BufferWithExtendableBuffer *const mContentTableBuffer; + const int mBlockSize; + const int mDataSize; +}; +} // namespace latinime +#endif /* LATINIME_SPARSE_TABLE_H */ 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/AndroidManifest.xml b/tests/AndroidManifest.xml index 09a63c590..4ca846be1 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -17,7 +17,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.inputmethod.latin.tests"> - <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> + <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> diff --git a/tests/src/com/android/inputmethod/latin/ExpandableDictionaryTests.java b/tests/src/com/android/inputmethod/latin/ExpandableDictionaryTests.java deleted file mode 100644 index 6aae1044e..000000000 --- a/tests/src/com/android/inputmethod/latin/ExpandableDictionaryTests.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin; - -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; - -/** - * Unit test for ExpandableDictionary - */ -@SmallTest -public class ExpandableDictionaryTests extends AndroidTestCase { - - private final static int UNIGRAM_FREQ = 50; - // See UserBinaryDictionary for more information about this variable. - // For tests, its actual value does not matter. - private final static int SHORTCUT_FREQ = 14; - - public void testAddWordAndGetWordFrequency() { - final ExpandableDictionary dict = new ExpandableDictionary(Dictionary.TYPE_USER); - - // Add words - dict.addWord("abcde", "abcde", UNIGRAM_FREQ, SHORTCUT_FREQ); - dict.addWord("abcef", null, UNIGRAM_FREQ + 1, 0); - - // Check words - assertFalse(dict.isValidWord("abcde")); - assertEquals(UNIGRAM_FREQ, dict.getWordFrequency("abcde")); - assertTrue(dict.isValidWord("abcef")); - assertEquals(UNIGRAM_FREQ+1, dict.getWordFrequency("abcef")); - - dict.addWord("abc", null, UNIGRAM_FREQ + 2, 0); - assertTrue(dict.isValidWord("abc")); - assertEquals(UNIGRAM_FREQ + 2, dict.getWordFrequency("abc")); - - // Add existing word with lower frequency - dict.addWord("abc", null, UNIGRAM_FREQ, 0); - assertEquals(UNIGRAM_FREQ + 2, dict.getWordFrequency("abc")); - - // Add existing word with higher frequency - dict.addWord("abc", null, UNIGRAM_FREQ + 3, 0); - assertEquals(UNIGRAM_FREQ + 3, dict.getWordFrequency("abc")); - } -} 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/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java index b9b52a6f3..3cb980cb0 100644 --- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java +++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java @@ -44,8 +44,8 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> { private static final String PREF_DEBUG_MODE = "debug_mode"; - // The message that sets the underline is posted with a 200 ms delay - protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 200; + // The message that sets the underline is posted with a 500 ms delay + protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 500; // The message that sets predictions is posted with a 200 ms delay protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS = 200; diff --git a/tests/src/com/android/inputmethod/latin/Ver4BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/Ver4BinaryDictionaryTests.java new file mode 100644 index 000000000..15d990c6d --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/Ver4BinaryDictionaryTests.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; + +import com.android.inputmethod.latin.makedict.BinaryDictEncoderUtils; +import com.android.inputmethod.latin.makedict.FormatSpec; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +// TODO: Add a test to evaluate the speed of operations of Ver4 dictionary. +@LargeTest +public class Ver4BinaryDictionaryTests extends AndroidTestCase { + private static final String TEST_LOCALE = "test"; + private static final String TEST_DICT_FILE_EXTENSION = ".testDict"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + // Note that dictVersion is different from dictionary format version and it never affects the + // dictionary format. + // TODO: Rename dictVersion to understandable name such as dictRevision. + private File createEmptyDictionaryAndGetTrieFile(final String dictVersion) throws IOException { + final File file = File.createTempFile(dictVersion, TEST_DICT_FILE_EXTENSION, + getContext().getCacheDir()); + file.delete(); + file.mkdir(); + Map<String, String> attributeMap = new HashMap<String, String>(); + attributeMap.put(FormatSpec.FileHeader.SUPPORTS_DYNAMIC_UPDATE_ATTRIBUTE, + FormatSpec.FileHeader.ATTRIBUTE_VALUE_TRUE); + if (BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), + 4 /* dictVersion */, attributeMap)) { + return new File(file, FormatSpec.TRIE_FILE_EXTENSION); + } else { + throw new IOException("Empty dictionary " + file.getAbsolutePath() + " " + + FormatSpec.TRIE_FILE_EXTENSION + " cannot be created."); + } + } + + public void testIsValidDictionary() { + final String dictVersion = Long.toString(System.currentTimeMillis()); + File trieFile = null; + try { + trieFile = createEmptyDictionaryAndGetTrieFile(dictVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + final BinaryDictionary binaryDictionary = new BinaryDictionary(trieFile.getAbsolutePath(), + 0 /* offset */, trieFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + assertTrue(binaryDictionary.isValidDictionary()); + } + + // TODO: Add large tests. + public void testReadProbability() { + final String dictVersion = Long.toString(System.currentTimeMillis()); + File trieFile = null; + try { + trieFile = createEmptyDictionaryAndGetTrieFile(dictVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + final BinaryDictionary binaryDictionary = new BinaryDictionary(trieFile.getAbsolutePath(), + 0 /* offset */, trieFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + + final int frequency = 100; + binaryDictionary.addUnigramWord("a", frequency); + binaryDictionary.addUnigramWord("aaa", frequency); + binaryDictionary.addUnigramWord("ab", frequency); + + assertEquals(frequency, binaryDictionary.getFrequency("a")); + assertEquals(frequency, binaryDictionary.getFrequency("aaa")); + assertEquals(frequency, binaryDictionary.getFrequency("ab")); + } + + public static int getCalculatedBigramProbabiliy(final BinaryDictionary binaryDictionary, + final int unigramFrequency, final int bigramFrequency) { + final int bigramFrequencyDiff = BinaryDictEncoderUtils.getBigramFrequencyDiff( + unigramFrequency, bigramFrequency); + return binaryDictionary.calculateProbability(unigramFrequency, bigramFrequencyDiff); + } + + // TODO: Add large tests. + public void testReadBigrams() { + final String dictVersion = Long.toString(System.currentTimeMillis()); + File trieFile = null; + try { + trieFile = createEmptyDictionaryAndGetTrieFile(dictVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + final BinaryDictionary binaryDictionary = new BinaryDictionary(trieFile.getAbsolutePath(), + 0 /* offset */, trieFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + + final int unigramFrequency = 1; + final int bigramFrequency0 = 10; + final int bigramFrequency1 = 1; + final int bigramFrequency2 = 15; + binaryDictionary.addUnigramWord("a", unigramFrequency); + binaryDictionary.addUnigramWord("aaa", unigramFrequency); + binaryDictionary.addUnigramWord("ab", unigramFrequency); + binaryDictionary.addBigramWords("a", "aaa", bigramFrequency0); + binaryDictionary.addBigramWords("a", "ab", bigramFrequency1); + binaryDictionary.addBigramWords("aaa", "ab", bigramFrequency2); + + assertEquals(binaryDictionary.calculateProbability(unigramFrequency, + bigramFrequency0), binaryDictionary.getBigramProbability("a", "aaa")); + assertEquals(binaryDictionary.calculateProbability(unigramFrequency, + bigramFrequency1), binaryDictionary.getBigramProbability("a", "ab")); + assertEquals(binaryDictionary.calculateProbability(unigramFrequency, + bigramFrequency2), binaryDictionary.getBigramProbability("aaa", "ab")); + + assertFalse(binaryDictionary.isValidBigram("aaa", "a")); + assertFalse(binaryDictionary.isValidBigram("ab", "a")); + assertFalse(binaryDictionary.isValidBigram("ab", "aaa")); + } + + // TODO: Add large tests. + public void testWriteUnigrams() { + final String dictVersion = Long.toString(System.currentTimeMillis()); + File trieFile = null; + try { + trieFile = createEmptyDictionaryAndGetTrieFile(dictVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + final BinaryDictionary binaryDictionary = new BinaryDictionary(trieFile.getAbsolutePath(), + 0 /* offset */, trieFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + + final int probability = 100; + binaryDictionary.addUnigramWord("aaa", probability); + binaryDictionary.addUnigramWord("abc", probability); + binaryDictionary.addUnigramWord("bcd", probability); + binaryDictionary.addUnigramWord("x", probability); + binaryDictionary.addUnigramWord("y", probability); + + assertEquals(probability, binaryDictionary.getFrequency("aaa")); + assertEquals(probability, binaryDictionary.getFrequency("abc")); + assertEquals(probability, binaryDictionary.getFrequency("bcd")); + assertEquals(probability, binaryDictionary.getFrequency("x")); + assertEquals(probability, binaryDictionary.getFrequency("y")); + } + + public void testWriteBigrams() { + final String dictVersion = Long.toString(System.currentTimeMillis()); + File trieFile = null; + try { + trieFile = createEmptyDictionaryAndGetTrieFile(dictVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + final BinaryDictionary binaryDictionary = new BinaryDictionary(trieFile.getAbsolutePath(), + 0 /* offset */, trieFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + + final int unigramProbability = 100; + final int bigramProbability = 10; + binaryDictionary.addUnigramWord("aaa", unigramProbability); + binaryDictionary.addUnigramWord("abb", unigramProbability); + binaryDictionary.addUnigramWord("bcc", unigramProbability); + binaryDictionary.addBigramWords("aaa", "abb", bigramProbability); + binaryDictionary.addBigramWords("aaa", "bcc", bigramProbability); + binaryDictionary.addBigramWords("abb", "aaa", bigramProbability); + binaryDictionary.addBigramWords("abb", "bcc", bigramProbability); + + final int probability = binaryDictionary.calculateProbability(unigramProbability, + bigramProbability); + assertEquals(true, binaryDictionary.isValidBigram("aaa", "abb")); + assertEquals(true, binaryDictionary.isValidBigram("aaa", "bcc")); + assertEquals(true, binaryDictionary.isValidBigram("abb", "aaa")); + assertEquals(true, binaryDictionary.isValidBigram("abb", "bcc")); + assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "abb")); + assertEquals(probability, binaryDictionary.getBigramProbability("aaa", "bcc")); + assertEquals(probability, binaryDictionary.getBigramProbability("abb", "aaa")); + assertEquals(probability, binaryDictionary.getBigramProbability("abb", "bcc")); + } + + public void testRemoveBigramWords() { + final String dictVersion = Long.toString(System.currentTimeMillis()); + File trieFile = null; + try { + trieFile = createEmptyDictionaryAndGetTrieFile(dictVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + final BinaryDictionary binaryDictionary = new BinaryDictionary(trieFile.getAbsolutePath(), + 0 /* offset */, trieFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + + final int unigramProbability = 100; + final int bigramProbability = 10; + binaryDictionary.addUnigramWord("aaa", unigramProbability); + binaryDictionary.addUnigramWord("abb", unigramProbability); + binaryDictionary.addUnigramWord("bcc", unigramProbability); + binaryDictionary.addBigramWords("aaa", "abb", bigramProbability); + binaryDictionary.addBigramWords("aaa", "bcc", bigramProbability); + binaryDictionary.addBigramWords("abb", "aaa", bigramProbability); + binaryDictionary.addBigramWords("abb", "bcc", bigramProbability); + + assertEquals(true, binaryDictionary.isValidBigram("aaa", "abb")); + assertEquals(true, binaryDictionary.isValidBigram("aaa", "bcc")); + assertEquals(true, binaryDictionary.isValidBigram("abb", "aaa")); + assertEquals(true, binaryDictionary.isValidBigram("abb", "bcc")); + + binaryDictionary.removeBigramWords("aaa", "abb"); + assertEquals(false, binaryDictionary.isValidBigram("aaa", "abb")); + binaryDictionary.addBigramWords("aaa", "abb", bigramProbability); + assertEquals(true, binaryDictionary.isValidBigram("aaa", "abb")); + + binaryDictionary.removeBigramWords("aaa", "bcc"); + assertEquals(false, binaryDictionary.isValidBigram("aaa", "bcc")); + binaryDictionary.removeBigramWords("abb", "aaa"); + assertEquals(false, binaryDictionary.isValidBigram("abb", "aaa")); + binaryDictionary.removeBigramWords("abb", "bcc"); + assertEquals(false, binaryDictionary.isValidBigram("abb", "bcc")); + + binaryDictionary.removeBigramWords("aaa", "abb"); + // Test remove non-existing bigram operation. + binaryDictionary.removeBigramWords("aaa", "abb"); + binaryDictionary.removeBigramWords("bcc", "aaa"); + } + +} 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/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java index 7c1decb71..c3e062b65 100644 --- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java +++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java @@ -214,9 +214,7 @@ public class UserHistoryDictionaryTests extends AndroidTestCase { public void testAddManyWords() { final String testFilenameSuffix = "testRandomWords" + System.currentTimeMillis(); - final int numberOfWords = - ExpandableBinaryDictionary.ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE ? - 10000 : 1000; + final int numberOfWords = 10000; final Random random = new Random(123456); clearHistory(testFilenameSuffix); try { diff --git a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java index 4e396a1cf..21fcf1117 100644 --- a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java @@ -44,7 +44,7 @@ public class StringUtilsTests extends AndroidTestCase { })); } - public void testContainsInExtraValues() { + public void testContainsInCommaSplittableText() { assertFalse("null", StringUtils.containsInCommaSplittableText("key", null)); assertFalse("empty", StringUtils.containsInCommaSplittableText("key", "")); assertFalse("not in 1 element", @@ -56,7 +56,28 @@ public class StringUtilsTests extends AndroidTestCase { assertTrue("in 2 elements", StringUtils.containsInCommaSplittableText("key", "key1,key")); } - public void testAppendToExtraValuesIfNotExists() { + public void testJoinCommaSplittableText() { + assertEquals("2 nulls", "", + StringUtils.joinCommaSplittableText(null, null)); + assertEquals("null and empty", "", + StringUtils.joinCommaSplittableText(null, "")); + assertEquals("empty and null", "", + StringUtils.joinCommaSplittableText("", null)); + assertEquals("2 empties", "", + StringUtils.joinCommaSplittableText("", "")); + assertEquals("text and null", "text", + StringUtils.joinCommaSplittableText("text", null)); + assertEquals("text and empty", "text", + StringUtils.joinCommaSplittableText("text", "")); + assertEquals("null and text", "text", + StringUtils.joinCommaSplittableText(null, "text")); + assertEquals("empty and text", "text", + StringUtils.joinCommaSplittableText("", "text")); + assertEquals("2 texts", "text1,text2", + StringUtils.joinCommaSplittableText("text1", "text2")); + } + + public void testAppendToCommaSplittableTextIfNotExists() { assertEquals("null", "key", StringUtils.appendToCommaSplittableTextIfNotExists("key", null)); assertEquals("empty", "key", @@ -77,7 +98,7 @@ public class StringUtilsTests extends AndroidTestCase { StringUtils.appendToCommaSplittableTextIfNotExists("key", "key1,key,key3")); } - public void testRemoveFromExtraValuesIfExists() { + public void testRemoveFromCommaSplittableTextIfExists() { assertEquals("null", "", StringUtils.removeFromCommaSplittableTextIfExists("key", null)); assertEquals("empty", "", StringUtils.removeFromCommaSplittableTextIfExists("key", "")); 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/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl b/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl index 4cd9c236b..072daa4e9 100644 --- a/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl +++ b/tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl @@ -87,11 +87,11 @@ public final class KeyboardTextsSet { return (text == null) ? LANGUAGE_DEFAULT[id] : text; } + // These texts' name should be aligned with the @string/<name> in + // values*/strings-action-keys.xml. private static final String[] RESOURCE_NAMES = { - // These texts' name should be aligned with the @string/<name> in values/strings.xml. // Labels for action. "label_go_key", - // "label_search_key", "label_send_key", "label_next_key", "label_done_key", diff --git a/tools/make-keyboard-text/res/values-ca/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-ca/donottranslate-more-keys.xml index 4cf742441..66393732c 100644 --- a/tools/make-keyboard-text/res/values-ca/donottranslate-more-keys.xml +++ b/tools/make-keyboard-text/res/values-ca/donottranslate-more-keys.xml @@ -71,7 +71,7 @@ U+0142: "ł" LATIN SMALL LETTER L WITH STROKE --> <string name="more_keys_for_l">l·l,ł</string> <!-- U+00B7: "·" MIDDLE DOT --> - <string name="more_keys_for_punctuation">"!fixedColumnOrder!4,·,!,\\,,\?,:,;,\@"</string> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!9,;,/,(,),#,·,!,\\,,\?,&,\\%,+,\",-,:,',\@"</string> <string name="more_keys_for_period">\?,·</string> <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA --> <string name="keylabel_for_spanish_row2_10">ç</string> 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">ñ,ń</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS --> + <string name="keylabel_for_swiss_row1_11">ü</string> + <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE --> + <string name="more_keys_for_swiss_row1_11">è</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="keylabel_for_swiss_row2_10">ö</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE --> + <string name="more_keys_for_swiss_row2_10">é</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="keylabel_for_swiss_row2_11">ä</string> + <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE --> + <string name="more_keys_for_swiss_row2_11">à</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">ç,ć,č</string> <!-- U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> <string name="more_keys_for_y">%,ÿ</string> + <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE --> + <string name="keylabel_for_swiss_row1_11">è</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS --> + <string name="more_keys_for_swiss_row1_11">ü</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE --> + <string name="keylabel_for_swiss_row2_10">é</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="more_keys_for_swiss_row2_10">ö</string> + <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE --> + <string name="keylabel_for_swiss_row2_11">à</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="more_keys_for_swiss_row2_11">ä</string> </resources> diff --git a/tools/make-keyboard-text/res/values-iw/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-iw/donottranslate-more-keys.xml index a1633316f..994e35ae9 100644 --- a/tools/make-keyboard-text/res/values-iw/donottranslate-more-keys.xml +++ b/tools/make-keyboard-text/res/values-iw/donottranslate-more-keys.xml @@ -28,6 +28,7 @@ <!-- U+00B1: "±" PLUS-MINUS SIGN U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN --> <string name="more_keys_for_plus">±,﬩</string> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,;,/,(|),)|(,#,!,\\,,\?,&,\\%,+,\",-,:,',\@"</string> <!-- The all letters need to be mirrored are found at http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> <string name="more_keys_for_left_parenthesis">!fixedColumnOrder!3,<|>,{|},[|]</string> 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..5f687db99 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> @@ -77,7 +83,7 @@ <string name="more_keys_for_currency_dollar">¢,£,€,¥,₱</string> <string name="keylabel_for_currency">$</string> <string name="more_keys_for_currency">$,¢,€,£,¥,₱</string> - <string name="more_keys_for_punctuation">"!fixedColumnOrder!4,#,!,\\,,\?,-,:,',\@"</string> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,;,/,(,),#,!,\\,,\?,&,\\%,+,\",-,:,',\@"</string> <!-- U+2020: "†" DAGGER U+2021: "‡" DOUBLE DAGGER U+2605: "★" BLACK STAR --> |